package com.xbongbong.pro.statistics.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.XbbConstant;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.AggTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.pro.bi.commons.pojo.AggFieldPojo;
import com.xbongbong.pro.bi.commons.pojo.vo.GroupSqlVO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.domain.entity.ChartEntity;
import com.xbongbong.pro.enums.errorcodes.BiErrorCodeEnum;
import com.xbongbong.pro.service.toolbox.statistic.util.ChartResultUtil;
import com.xbongbong.pro.statistic.ChartDrillItemPojo;
import com.xbongbong.pro.statistic.enums.AdvancedComputingFirstEnum;
import com.xbongbong.pro.statistic.enums.ChartDrillWayEnum;
import com.xbongbong.pro.statistic.enums.ChartTypeEnum;
import com.xbongbong.pro.statistic.enums.DrillDirEnum;
import com.xbongbong.pro.statistic.enums.DrillFieldEnum;
import com.xbongbong.pro.statistic.enums.NumFormatEnum;
import com.xbongbong.pro.statistic.enums.RowColEnum;
import com.xbongbong.pro.statistic.enums.RowColIndexEnum;
import com.xbongbong.pro.statistic.help.ChartResultHelp;
import com.xbongbong.pro.statistic.help.DrillHelp;
import com.xbongbong.pro.statistic.help.FieldAnalysisHelp;
import com.xbongbong.pro.statistic.pojo.DwTriggerConditionPojo;
import com.xbongbong.pro.statistic.pojo.vo.DataWarningQueryListVO;
import com.xbongbong.pro.statistic.pojo.vo.DataWarningQueryVO;
import com.xbongbong.pro.statistic.result.pojo.ChartResultPojo;
import com.xbongbong.pro.statistic.result.pojo.ChartStatisticsPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultChartFieldInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultChartInfoPojo;
import com.xbongbong.pro.statistic.result.pojo.DrillResultPojo;
import com.xbongbong.pro.statistic.result.pojo.FieldAttrPojo;
import com.xbongbong.pro.statistic.result.pojo.WarningValuePojo;
import com.xbongbong.pro.statistic.result.pojo.vo.ChartAnalysisVO;
import com.xbongbong.pro.statistic.result.pojo.vo.ResultTableVO;
import com.xbongbong.pro.statistics.pojo.dto.ChartAnalysisDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 统计表渲染公有方法
 * @ClassName StatisticsTableHelper
 * @Author 梁鲁江
 * 创建时间 2022/9/23 13:42
 * 修改时间  2022/9/23 13:42
 **/
@Component
public class StatisticsTableVOHelper {
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private ChartResultHelp chartResultHelp;
    @Resource
    private CkResultHelp ckResultHelp;
    @Resource
    private DrillHelp drillHelp;

    public Logger logger = LoggerFactory.getLogger(getClass());
    public ChartAnalysisVO statisticsChartAnalysis(ChartAnalysisDTO chartAnalysisDTO,Map<String, Map<String, String>> attrLinkMap) throws XbbException {
        ChartAnalysisVO chartAnalysisVO = new ChartAnalysisVO();
        ChartEntity chartEntity = chartAnalysisDTO.getChartEntity();
        JSONArray jsonArray = chartAnalysisDTO.getResultArray();
        Map<String, AggFieldPojo> aggFieldMap = chartAnalysisDTO.getAggFieldMap();
        //左侧（列分组规则+行分组规则+行分组数据）
        List<ChartStatisticsPojo> headChild = new ArrayList<>();
        JSONArray colGroupAttr = chartEntity.getColGroupAttr();
        JSONArray rowGroupAttr = chartEntity.getRowGroupAttr();
        JSONArray summaryAttr = chartEntity.getSummaryAttr();
        JSONObject head = new JSONObject();
        ResultTableVO resultTableVO = new ResultTableVO();

        List<FieldAttrPojo> rowGroupAttrList = JSONArray.parseArray(rowGroupAttr.toJSONString(), FieldAttrPojo.class);
        List<FieldAttrPojo> colGroupAttrList = JSONArray.parseArray(colGroupAttr.toJSONString(), FieldAttrPojo.class);

        //处理左侧列分组规则
        if(CollectionsUtil.isNotEmpty(colGroupAttrList)){
            for (FieldAttrPojo fieldAttrPojo : colGroupAttrList) {
                String labelName = fieldAttrPojo.getLabelName();
                String label = fieldAttrPojo.getLabel();
                String attrName = fieldAttrPojo.getAttrName();
                ChartStatisticsPojo pojo = new ChartStatisticsPojo();
                pojo.setKey(fieldAttrPojo.getAttr() + "&" + fieldAttrPojo.getFieldType());
                pojo.setValue(labelName);
                if (Objects.equals(labelName,label)) {
                    boolean flag = FieldTypeEnum.SUB_FORM.getType().intValue() == fieldAttrPojo.getFieldType()  || StringUtil.isEmpty(label);
                    if (flag) {
                        pojo.setValue(attrName);
                    } else {
                        pojo.setValue(Arrays.asList(label.split("--")).get(0) + "--" + attrName);
                    }
                }
                pojo.setHead(true);
                pojo.setFormId(fieldAttrPojo.getFormId());
                if (fieldAttrPojo.getDateGroupType() != null) {
                    pojo.setDateGroupType(fieldAttrPojo.getDateGroupType());
                }
                headChild.add(pojo);
            }
        }
        //处理左侧行分组规则
        if(CollectionsUtil.isNotEmpty(rowGroupAttrList)){
            ChartStatisticsPojo rowChartPojo = new ChartStatisticsPojo();
            row2setLevel(rowGroupAttrList, rowChartPojo, 0);
            headChild.add(rowChartPojo);
        }
        Map<String,ChartStatisticsPojo> rowMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //汇总字段
        List<FieldAttrPojo> summaryAttrList = null;
        Map<String, FieldAttrPojo> summaryAttrMap = new HashMap<>();
        if(CollectionsUtil.isNotEmpty(summaryAttr)){
            summaryAttrList = JSONArray.parseArray(summaryAttr.toJSONString(), FieldAttrPojo.class);
            for (int i = 0; i < summaryAttrList.size(); i++) {
                FieldAttrPojo fieldAttrPojo = summaryAttrList.get(i);
                summaryAttrMap.put(fieldAttrPojo.getAttr() + "&" + fieldAttrPojo.getFieldType() + "&" + i, fieldAttrPojo);
            }
        }
        Map<String,ChartStatisticsPojo> colMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 处理数据 （如处理右侧行分组规则......）
        handleTableData(jsonArray, rowGroupAttrList,rowMap,colGroupAttrList,colMap,summaryAttrMap,aggFieldMap,chartEntity.getSum(), chartAnalysisDTO,chartEntity,resultTableVO,attrLinkMap);
        Collection<ChartStatisticsPojo> values = rowMap.values();
        List<ChartStatisticsPojo> rowList = new ArrayList<>();
        //左侧表头字段处理
        if(Objects.equals(chartEntity.getSum(), 0) || Objects.equals(chartEntity.getSum(),2)){
            //小计
            subTotalHeadHandle(colGroupAttrList, values, rowList);
            //多选时总计的数据格式已经在handleTableData中处理过了
        }else if(Objects.equals(chartEntity.getSum(), 1)){
            //总计
            sumTotalHeadHadnle(values, rowList,rowGroupAttr);
        }
        headChild.addAll(rowList);
        head.put("child", headChild);
        resultTableVO.setHead(head);

        List<ChartStatisticsPojo> body = new ArrayList<>(colMap.values());
        resultTableVO.setBody(JSONArray.parseArray(JSONObject.toJSONString(body)));
        chartAnalysisVO.setResult(JSONObject.parseObject(JSONObject.toJSONString(resultTableVO)));
        return chartAnalysisVO;
    }

    private void sumTotalHeadHadnle(Collection<ChartStatisticsPojo> values, List<ChartStatisticsPojo> rowList,JSONArray rowGroupAttr) {
        if(CollectionsUtil.isNotEmpty(values)){
            rowList.addAll(values);
        }
        //判断rowGroupAttr这步操作 对应的bugId： 51987【仪表盘】统计表添加查询条件后，列表统计的条数与实际不符
        else if(CollectionsUtil.isEmpty(rowGroupAttr)){
            //没有行分组的处理  固定2行空格
            for (int i = 0; i < 2; i++) {
                ChartStatisticsPojo statisticsPojo = new ChartStatisticsPojo();
                statisticsPojo.setKey("");
                statisticsPojo.setValue("");
                statisticsPojo.setIsSummary(true);
                rowList.add(statisticsPojo);
            }
        }
    }

    private void subTotalHeadHandle(List<FieldAttrPojo> colGroupAttrList, Collection<ChartStatisticsPojo> values, List<ChartStatisticsPojo> rowList) {
        if(CollectionsUtil.isNotEmpty(values)){
            for (ChartStatisticsPojo value : values) {
                rowList.add(value);
                ChartStatisticsPojo statisticsPojo = new ChartStatisticsPojo();
                statisticsPojo.setKey("");
                statisticsPojo.setValue(I18nMessageUtil.getMessage(CommonConstant.SUBTOTAL));
                statisticsPojo.setIsSummary(true);
                rowList.add(statisticsPojo);
            }
        }else {
            //没有行分组的处理
            if(CollectionUtils.isNotEmpty(colGroupAttrList)){
                ChartStatisticsPojo statisticsPojo = new ChartStatisticsPojo();
                statisticsPojo.setKey("");
                statisticsPojo.setValue("");
                statisticsPojo.setIsSummary(true);
                rowList.add(statisticsPojo);
            }
            ChartStatisticsPojo statisticsPojo = new ChartStatisticsPojo();
            statisticsPojo.setKey("");
            statisticsPojo.setValue(I18nMessageUtil.getMessage(CommonConstant.SUBTOTAL));
            statisticsPojo.setIsSummary(true);
            rowList.add(statisticsPojo);
        }
    }

    /**
     * 设置行分组字段的父子层级关系（仅规则部分）
     * @param rowGroupAttrList
     * @param rowChartPojo
     * @param size
     * @return void
     */
    private void row2setLevel(List<FieldAttrPojo> rowGroupAttrList, ChartStatisticsPojo rowChartPojo, int size) {
        FieldAttrPojo fieldAttrPojo = rowGroupAttrList.get(size);
        String labelName = fieldAttrPojo.getLabelName();
        String label = fieldAttrPojo.getLabel();
        String attrName = fieldAttrPojo.getAttrName();
        Integer fieldType = fieldAttrPojo.getFieldType();
        rowChartPojo.setKey(fieldAttrPojo.getAttr() + "&" + fieldType);
        rowChartPojo.setValue(labelName);
        if (Objects.equals(labelName,label)) {
            //判空label，防止钻取目标字段无label和labelName，从而导致label.split出错
            boolean flag = FieldTypeEnum.SUB_FORM.getType().intValue() == fieldType || StringUtil.isEmpty(label);
            if (flag) {
                rowChartPojo.setValue(attrName);
            } else {
                rowChartPojo.setValue(Arrays.asList(label.split("--")).get(0) + "--" + attrName);
            }
        }
        rowChartPojo.setHead(true);
        rowChartPojo.setFormId(fieldAttrPojo.getFormId());
        if (size < rowGroupAttrList.size() - 1) {
            ChartStatisticsPojo pojo = new ChartStatisticsPojo();
            List<ChartStatisticsPojo> rowChild = new ArrayList<>();
            size++;
            row2setLevel(rowGroupAttrList, pojo,size);
            rowChild.add(pojo);
            rowChartPojo.setChild(rowChild);
        }
        if (fieldAttrPojo.getDateGroupType() != null) {
            rowChartPojo.setDateGroupType(fieldAttrPojo.getDateGroupType());
        }
    }

    /**
     * 处理数据
     * @param jsonArray 数据
     * @param rowGroupAttrList 行分组
     * @param rowMap 行数据载体返回
     * @param colGroupAttrList 列分组
     * @param colMap 列数据（包含统计值）载体返回
     * @param summaryAttrMap 统计值
     * @param aggFieldMap  统计值的别名映射关系
     * @param sum 汇总方式：0小计，1总计
     * @param chartAnalysisDTO
     */
    private void handleTableData(JSONArray jsonArray, List<FieldAttrPojo> rowGroupAttrList, Map<String, ChartStatisticsPojo> rowMap, List<FieldAttrPojo> colGroupAttrList, Map<String, ChartStatisticsPojo> colMap, Map<String, FieldAttrPojo> summaryAttrMap, Map<String, AggFieldPojo> aggFieldMap, Integer sum, ChartAnalysisDTO chartAnalysisDTO, ChartEntity chartEntity, ResultTableVO resultTableVO,Map<String, Map<String, String>> attrLinkMap) throws XbbException {
        Map<String, Map<String, ChartStatisticsPojo>> sumMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 同环比原始值map，key:日期时间戳，val：原始统计值
        Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        boolean isYearChain = EsUtil.isYearChain(chartEntity);
        Integer dateIndex = null;
        FieldAttrPojo dateFieldAttrPojo = null;
        // 处理数据预警
        Map<String,Object> dwVOMap = chartResultHelp.getDWQueryListVO(chartAnalysisDTO,chartEntity);
        DataWarningQueryListVO dataWarningQueryListVO = (DataWarningQueryListVO) dwVOMap.get("dataWarningQueryListVO");
        // 获取某一张图的总钻取信息pojo，包含总筛选条件、图内字段钻取信息map
        DrillResultChartInfoPojo drillResultChartInfoPojo = getDrillResultChartInfoPojo(chartAnalysisDTO, chartEntity);

        for (int dataI = 0; dataI < jsonArray.size(); dataI++) {
            JSONObject resultObj = jsonArray.getJSONObject(dataI);
            if(resultObj == null){
                continue;
            }
            // 行、列表头数据处理
            setRowOrColMap(DrillFieldEnum.ROW_GROUP_ATTR.getAlias(), drillResultChartInfoPojo, rowGroupAttrList, rowMap, resultObj, chartAnalysisDTO,chartEntity,attrLinkMap);
            setRowOrColMap(DrillFieldEnum.COL_GROUP_ATTR.getAlias(), drillResultChartInfoPojo, colGroupAttrList, colMap, resultObj, chartAnalysisDTO,chartEntity,attrLinkMap);
            if(aggFieldMap !=null && !aggFieldMap.isEmpty()) {
                StringBuffer outKeyBuffer = new StringBuffer();
                if(CollectionsUtil.isNotEmpty(rowGroupAttrList)){
                    for (int i = 0; i < rowGroupAttrList.size(); i++) {
                        FieldAttrPojo fieldAttrPojo = rowGroupAttrList.get(i);
                        String val;
                        if (!Objects.isNull(fieldAttrPojo.getValue()) && StringUtil.isNotEmpty(fieldAttrPojo.getValueText())) {
                            // 钻取之后获取转化信息特殊处理
                            val = fieldAttrPojo.getValue().toString();
                        } else {
                            // 获取转化信息
                            val = FastJsonHelper.getStringOrDefault(resultObj, fieldAttrPojo.getAttr(), "");
                        }
                        outKeyBuffer.append(val).append("|");
                        // 同环比定位日期位置
                        if (isYearChain && EsUtil.isDateByEsalias(fieldAttrPojo)) {
                            dateIndex = RowColIndexEnum.getCodeByTypeAndIndex(RowColEnum.ROW.getValue(), i);
                            dateFieldAttrPojo = fieldAttrPojo;
                        }
                    }
                }
                if(CollectionsUtil.isNotEmpty(colGroupAttrList)){
                    for (int i = 0; i < colGroupAttrList.size(); i++) {
                        FieldAttrPojo fieldAttrPojo = colGroupAttrList.get(i);
                        String val;
                        if (!Objects.isNull(fieldAttrPojo.getValue()) && StringUtil.isNotEmpty(fieldAttrPojo.getValueText())) {
                            // 钻取之后获取转化信息特殊处理
                            val = fieldAttrPojo.getValue().toString();
                        } else {
                            // 获取转化信息
                            val = FastJsonHelper.getStringOrDefault(resultObj, fieldAttrPojo.getAttr(), "");
                        }
                        outKeyBuffer.append(val).append("|");
                        // 同环比定位日期位置
                        if (isYearChain && EsUtil.isDateByEsalias(fieldAttrPojo)) {
                            dateIndex = RowColIndexEnum.getCodeByTypeAndIndex(RowColEnum.COL.getValue(), i);
                            dateFieldAttrPojo = fieldAttrPojo;
                        }
                    }
                }
                String outKey = outKeyBuffer.toString();
                Map<String, ChartStatisticsPojo> innerSumMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                sumMap.put(outKey,innerSumMap);
                for (Map.Entry<String, AggFieldPojo> stringAggFieldPojoEntry : aggFieldMap.entrySet()) {
                    String key = stringAggFieldPojoEntry.getKey();
                    AggFieldPojo aggFieldPojo =  stringAggFieldPojoEntry.getValue();
                    String attr = aggFieldPojo.getAttr();
                    String aggName = attr + "&" + aggFieldPojo.getFieldType() + "&" + aggFieldPojo.getIndex();
                    ChartStatisticsPojo pojo = innerSumMap.get(aggName);
                    if (pojo == null) {
                        pojo = new ChartStatisticsPojo(new ArrayList<>());
                        innerSumMap.put(aggName,pojo);
                    }
                    pojo.setOutKey(outKey);
                    pojo.setKey(aggName);
                    String valueName = "";
                    //判空
                    String aggTypeName = aggFieldPojo.getAggTypeEnum() == null ? "" : aggFieldPojo.getAggTypeEnum().getName();
                    valueName = StringConstant.LEFT_BRACKETS + aggTypeName + ckResultHelp.splicingSuffix(aggFieldPojo.getAdvancedComputing(), ChartTypeEnum.getByCode(chartEntity.getChartType()));
                    pojo.setValue(aggFieldPojo.getLabelName() + valueName);
                    pojo.setIsLeaf(true);
                    pojo.setAggTypeEnum(aggFieldPojo.getAggTypeEnum());
                    List<String> originValues = pojo.getOriginValues();
                    if(originValues == null){
                        originValues = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    }
                    String esValue = FastJsonHelper.getStringOrDefault(resultObj, key, "");
                    originValues.add(esValue);
                    pojo.setOriginValues(originValues);
                    FieldAttrPojo summaryFieldAttrPojo = summaryAttrMap.get(aggName);
                    summaryFieldAttrPojo.setDateFieldIndex(dateIndex);
                    pojo.setSummaryFieldAttrPojo(summaryFieldAttrPojo);
                    pojo.setDateFieldAttrPojo(dateFieldAttrPojo);
                }
                // 同环比原始值map组装
                if (isYearChain) {
                    Map<String, ChartStatisticsPojo> yearChainValMap = (LinkedHashMap<String, ChartStatisticsPojo>) CloneUtil.deepClone(innerSumMap);
                    yearChainOriginValMap.put(outKey, yearChainValMap);
                }
            }
        }
        //用户没有手动设置排序，并且列字段为下拉框单选类型，需要在这里调整一下顺序
        if(chartAnalysisDTO.getChartResultPojo().getSortStatisticsMap() == null){
            rebuildColFieldSort(colGroupAttrList,colMap);
        }

        List<String> rowKeyList = new ArrayList<>();
        //多选时右侧总计使用
        Map<String,List<String>> rowKeyMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //行分组的处理
        for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : rowMap.entrySet()) {
            List<String> rowKeyValueList = new ArrayList<>();
            ChartStatisticsPojo value = stringChartStatisticsPojoEntry.getValue();
            StringBuffer parentKey = value.getParentKey();
            if(parentKey == null){
                parentKey = new StringBuffer();
            }
            parentKey.append(value.getOriginValue()).append("|");
            value.setParentKey(parentKey);
            setRowChild(value,rowKeyList,rowKeyValueList);
            rowKeyMap.put(stringChartStatisticsPojoEntry.getKey(),rowKeyValueList);
        }
        //组装源数据，并设置小计、总计值
        switch (sum){
            case 0:
                //小计
                subTotalResultHandle(colMap,rowKeyList,rowGroupAttrList,colGroupAttrList,sumMap,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
                break;
            case 1:
                //总计
                sumTotalResultHandle(colMap,rowKeyList,rowGroupAttrList,colGroupAttrList,sumMap,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO,summaryAttrMap,aggFieldMap,chartEntity,resultTableVO);
                break;
            case 2:
                //小计 & 总计:因为小计值是在组装源数据时放进去的，因此多选时，走小计的逻辑，然后额外组装右侧总计、下方总计
                subTotalResultHandle(colMap,rowKeyList,rowGroupAttrList,colGroupAttrList,sumMap,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
                //多选情况下获取右侧总计值
                if(CollectionUtils.isNotEmpty(colGroupAttrList)){
                    getRightSumTotal(rowGroupAttrList,colMap,summaryAttrMap,aggFieldMap,chartAnalysisDTO,chartEntity,rowKeyList,rowKeyMap);
                }
                //下方总计
                summaryStructure(chartAnalysisDTO, chartEntity, aggFieldMap, resultTableVO, rowGroupAttrList, colGroupAttrList, summaryAttrMap, colMap);
                break;
            default:
                break;
        }
        if (Objects.nonNull(dataWarningQueryListVO)){
            resultTableVO.setWarningFlag(dataWarningQueryListVO.getWarningFlag());
        }else {
            resultTableVO.setWarningFlag(false);
        }
    }

    private void sumTotalResultHandle(Map<String, ChartStatisticsPojo> colMap, List<String> rowKeyList, List<FieldAttrPojo> rowGroupAttrList, List<FieldAttrPojo> colGroupAttrList, Map<String, Map<String, ChartStatisticsPojo>> sumMap, Map<String, ChartStatisticsPojo> rowMap, Integer sum, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO, ChartAnalysisDTO chartAnalysisDTO,Map<String, FieldAttrPojo> summaryAttrMap, Map<String, AggFieldPojo> aggFieldMap,ChartEntity chartEntity,ResultTableVO resultTableVO) throws XbbException {
        if((CollectionUtils.isNotEmpty(rowGroupAttrList) && CollectionUtils.isNotEmpty(colGroupAttrList)) || CollectionUtils.isNotEmpty(colGroupAttrList)){
            //行列 、 列
            getRowAndColData(colMap,rowKeyList,sumMap,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
            //右侧总计
            getRightSumTotal(rowGroupAttrList,colMap,summaryAttrMap,aggFieldMap,chartAnalysisDTO,chartEntity,rowKeyList,null);
        }else if(CollectionUtils.isNotEmpty(rowGroupAttrList)){
            //行，没有右侧总计
            sumTotalRowResult(colMap,sum,sumMap,yearChainOriginValMap,dataWarningQueryListVO,rowKeyList);
        }
        //下方总计
        summaryStructure(chartAnalysisDTO, chartEntity, aggFieldMap, resultTableVO, rowGroupAttrList, colGroupAttrList, summaryAttrMap, colMap);
    }

    /**
     * 总计设置了行
     *
     * @param colMap
     * @param sum
     * @param sumMap
     * @param yearChainOriginValMap
     * @param dataWarningQueryListVO
     * @param rowKeyList
     * @author zyy
     * @date 2022/8/23
     * @version v1.0
     */
    private void sumTotalRowResult(Map<String, ChartStatisticsPojo> colMap, Integer sum, Map<String, Map<String, ChartStatisticsPojo>> sumMap, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO, List<String> rowKeyList) {
        //总计(仅有行分组的时候不需要右侧总计)
        int index = 0;
        for (String rowKey : rowKeyList) {
            Map<String, ChartStatisticsPojo> innerMap = sumMap.get(rowKey);
            index ++;
            boolean setWarningFlag = (++index == rowKeyList.size());
            if(innerMap != null){
                for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : innerMap.entrySet()) {
                    String key = stringChartStatisticsPojoEntry.getKey();
                    ChartStatisticsPojo chartStatisticsPojo = stringChartStatisticsPojoEntry.getValue();
                    List<String> originValues = chartStatisticsPojo.getOriginValues();
                    FieldAttrPojo summaryFieldAttrPojo = chartStatisticsPojo.getSummaryFieldAttrPojo();
                    if (CollectionUtils.isEmpty(originValues)) {
                        continue;
                    }
                    if(colMap.containsKey(key)){
                        // 避免对原对象内的值产生影响
                        List<String> originValuesCopy = new ArrayList<>(originValues);
                        if(CollectionsUtil.isNotEmpty(originValuesCopy)){
                            ChartStatisticsPojo colMapPojo = colMap.get(key);
                            // 同环比处理
                            if (!yearChainOriginValMap.isEmpty()) {
                                String oldVal = getOldVal4StatisticsTable(rowKey, "", yearChainOriginValMap, key, colMapPojo);
                                // innerOriginValues里面永远只有一个值，直接get(0)
                                String value = chartResultHelp.getYearChainValue(summaryFieldAttrPojo, oldVal, originValuesCopy.get(0));
                                originValuesCopy.clear();
                                originValuesCopy.add(value);
                            }
                            colMapPojo.getOriginValues().addAll(originValuesCopy);
                        }
                        // 处理预警数据
                        handleDataWarningData(chartStatisticsPojo.getSummaryFieldAttrPojo(), dataWarningQueryListVO, originValuesCopy, chartStatisticsPojo,setWarningFlag, sum);
                    }else {
                        //列的总计
                        // 避免对原对象内的值产生影响
                        List<String> originValuesCopy = new ArrayList<>(originValues);
                        // 同环比处理
                        if (!yearChainOriginValMap.isEmpty()) {
                            String oldVal = getOldVal4StatisticsTable(rowKey, "", yearChainOriginValMap, key, chartStatisticsPojo);
                            // originValues里面永远只有一个值，直接get(0)
                            String value = chartResultHelp.getYearChainValue(summaryFieldAttrPojo, oldVal, originValuesCopy.get(0));
                            originValuesCopy.clear();
                            originValuesCopy.add(value);
                            chartStatisticsPojo.setOriginValues(originValuesCopy);
                        }
                        colMap.put(key, chartStatisticsPojo);
                        // 处理预警数据
                        handleDataWarningData(chartStatisticsPojo.getSummaryFieldAttrPojo(), dataWarningQueryListVO, originValuesCopy, chartStatisticsPojo,setWarningFlag, sum);
                    }
                }
            }
        }
        for (String key : colMap.keySet()) {
            ChartStatisticsPojo pojo = colMap.get(key);
            // 格式化
            List<String> sumList = new ArrayList<>(pojo.getOriginValues());
            FieldAttrPojo summaryFieldAttrPojo = pojo.getSummaryFieldAttrPojo();
            ckResultHelp.getNumFormat(summaryFieldAttrPojo, sumList);
            pojo.getValues().addAll(sumList);
            // 处理预警数据
            handleDataWarningData(summaryFieldAttrPojo, dataWarningQueryListVO,pojo.getOriginValues(), pojo,true, sum);
        }
    }

    /**
     * 统计表-右侧总计值
     *
     * @param rowGroupAttrList 行分组字段数组
     * @param colMap 列分组字段
     * @param summaryAttrMap 原汇总字段映射数组
     * @param aggFieldMap 汇总字段映射数组
     * @param chartAnalysisDTO 入参实体
     * @param chartEntity 图表实体
     * @param rowKeyList  行数据key数组
     * @param rowKeyMap  行分组字段映射容器
     * @author zyy
     * @date 2022/8/22
     * @version v1.0
     */
    private void getRightSumTotal(List<FieldAttrPojo> rowGroupAttrList, Map<String, ChartStatisticsPojo> colMap, Map<String, FieldAttrPojo> summaryAttrMap, Map<String, AggFieldPojo> aggFieldMap, ChartAnalysisDTO chartAnalysisDTO, ChartEntity chartEntity, List<String> rowKeyList,Map<String,List<String>> rowKeyMap) throws XbbException {
        JSONArray rightJsonArray = chartAnalysisDTO.getSumRightJsonArray();
        Map<String,ChartStatisticsPojo> tmpValueMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<ChartStatisticsPojo> child = new ArrayList<>();
        if(CollectionUtils.isEmpty(rowGroupAttrList)){
            //没有行，直接从结果集取数据 (结果集中最多有一个结果)
            for (int i = 0; i < rightJsonArray.size(); i++) {
                JSONObject jsonObject = rightJsonArray.getJSONObject(i);
                if(jsonObject == null){
                    continue;
                }
                getRightSumTotalData(summaryAttrMap, aggFieldMap, tmpValueMap, child, jsonObject);
            }
        }else{
            Map<String,JSONObject> resultMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //列跟行分组都存在
            //拼接key，用来保证右侧总计值跟行的顺序相同
            for (int dataI = 0; dataI < rightJsonArray.size(); dataI++) {
                JSONObject resultObj = rightJsonArray.getJSONObject(dataI);
                if(resultObj == null){
                    continue;
                }
                StringBuilder outKeyBuffer = new StringBuilder();
                for (FieldAttrPojo fieldAttrPojo : rowGroupAttrList) {
                    String esValue;
                    if (!Objects.isNull(fieldAttrPojo.getValue())) {
                        // 钻取之后获取转化信息特殊处理
                        esValue = fieldAttrPojo.getValue().toString();
                    } else {
                        // 获取转化信息
                        esValue = getEsValue(resultObj, chartEntity, fieldAttrPojo, fieldAttrPojo.getAttr(), fieldAttrPojo.getFieldType());
                    }
                    outKeyBuffer.append(esValue).append("|");
                }
                resultMap.put(outKeyBuffer.toString(),resultObj);
            }
            if(rowKeyMap == null){
                //仅总计时，直接根据行维度，匹配右侧总计的值
                for (String key : rowKeyList) {
                    JSONObject jsonObject = resultMap.get(key);
                    if(Objects.isNull(jsonObject)){
                        logger.error("统计表右侧总计不存在，chartId： "
                                        + chartEntity.getId()
                                        + "，  corpid:  " + chartEntity.getCorpid()
                                        + "，  总表数据： " + rowKeyList
                                        + "，  右侧数据： " + resultMap.keySet()
                                        + "，  当前数据： " + key);
                        throw new XbbException(BiErrorCodeEnum.API_ERROR_241023);
                    }
                    getRightSumTotalData(summaryAttrMap, aggFieldMap, tmpValueMap, child, jsonObject);
                }
            }else{
                //小计、总计多选时，需要处理小计对应的右侧总计值
                for (Map.Entry<String, List<String>> stringListEntry : rowKeyMap.entrySet()) {
                    for (String key : stringListEntry.getValue()) {
                        JSONObject jsonObject = resultMap.get(key);
                        getRightSumTotalData(summaryAttrMap, aggFieldMap, tmpValueMap, child, jsonObject);
                    }
                    //小计的右侧总计置空
                    for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : tmpValueMap.entrySet()) {
                        ChartStatisticsPojo entry = stringChartStatisticsPojoEntry.getValue();
                        entry.getValues().add("");
                    }
                }
            }
        }
        ChartStatisticsPojo statisticsPojo = new ChartStatisticsPojo();
        statisticsPojo.setKey("");
        statisticsPojo.setValue(I18nMessageUtil.getMessage(CommonConstant.TOTAL));
        statisticsPojo.setIsSummary(true);
        statisticsPojo.setChild(child);
        colMap.put("",statisticsPojo);
    }

    /**
     * 获取右侧总计数据
     *
     * @param summaryAttrMap 原汇总字段映射容器
     * @param aggFieldMap 汇总字段映射数据
     * @param tmpValueMap 临时容器，存储每个
     * @param child 存储最后的数据
     * @param jsonObject 原数据
     * @author zyy
     * @date 2022/8/22
     * @version v1.0
     */
    private void getRightSumTotalData(Map<String, FieldAttrPojo> summaryAttrMap, Map<String, AggFieldPojo> aggFieldMap, Map<String, ChartStatisticsPojo> tmpValueMap, List<ChartStatisticsPojo> child, JSONObject jsonObject) {
        for (String s : aggFieldMap.keySet()) {
            AggFieldPojo aggFieldPojo = aggFieldMap.get(s);
            ChartStatisticsPojo statisticsPojo = new ChartStatisticsPojo();
            statisticsPojo.setKey(aggFieldPojo.getAttr());
            statisticsPojo.setValue(aggFieldPojo.getLabelName() + " ( " + I18nMessageUtil.getMessage(aggFieldPojo.getAggTypeEnum().getName()) + " ) ");
            statisticsPojo.setIsSummary(false);
            statisticsPojo.setIsLeaf(true);
            String aggName = aggFieldPojo.getAttr() + "&" + aggFieldPojo.getFieldType() + "&" + aggFieldPojo.getIndex();
            FieldAttrPojo fieldAttrPojo = summaryAttrMap.get(aggName);
            int accuracy = fieldAttrPojo.getAccuracy() == null ? 0 : fieldAttrPojo.getAccuracy();
            Integer percentUsed = fieldAttrPojo.getPercentUsed();
            Integer groupingUsed = fieldAttrPojo.getGroupingUsed() == null ? fieldAttrPojo.getAmountFlag() : fieldAttrPojo.getGroupingUsed();
            Integer numFormat = fieldAttrPojo.getNumFormat();
            NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(numFormat);
            String unit = numFormatEnum.getNoYuanUnit();
            String formatVal = "";
            // 同环比暂不计算列汇总
            if(AdvancedComputingFirstEnum.noneYearChain(aggFieldPojo.getAdvancedComputing()) && StringUtils.isNotBlank(jsonObject.getString(s))){
                String newVal = String.valueOf(ChartResultUtil.formatVal4Num(new BigDecimal(jsonObject.getString(s)), numFormatEnum, FieldAnalysisHelp.isPercentUsedOfAccuracy(percentUsed,accuracy)));
                formatVal = attrDecimalPrecisionHelper.getNumberFormat(newVal, accuracy, groupingUsed, percentUsed);
                if (StringUtil.isNotEmpty(unit)) {
                    formatVal += unit;
                }
            }
            List<String> valueList;
            if(tmpValueMap.containsKey(s)){
                ChartStatisticsPojo chartStatisticsPojo = tmpValueMap.get(s);
                valueList = chartStatisticsPojo.getValues();
            }else{
                valueList = new ArrayList<>();
                statisticsPojo.setValues(valueList);
                tmpValueMap.put(s,statisticsPojo);
                child.add(statisticsPojo);
            }
            valueList.add(formatVal);
        }
    }

    /**
     * 统计表数据以及小计值处理
     *
     * @param colMap 列结果集
     * @param rowKeyList 行数据key数组
     * @param rowGroupAttrList 行分组字段数组
     * @param colGroupAttrList 列分组字段数组
     * @param sumMap 存储总的数据
     * @param rowMap 行数据（最后拼接行左侧表头使用）
     * @param sum 0-小计  1-总计  2-小计&总计
     * @param yearChainOriginValMap 同环比实体
     * @param dataWarningQueryListVO 数据预警实体
     * @param chartAnalysisDTO 入参实体
     * @author zyy
     * @date 2022/8/22
     * @version v1.0
     */
    private void subTotalResultHandle(Map<String, ChartStatisticsPojo> colMap, List<String> rowKeyList, List<FieldAttrPojo> rowGroupAttrList, List<FieldAttrPojo> colGroupAttrList, Map<String, Map<String, ChartStatisticsPojo>> sumMap, Map<String, ChartStatisticsPojo> rowMap, Integer sum, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO, ChartAnalysisDTO chartAnalysisDTO) {
        if((CollectionUtils.isNotEmpty(rowGroupAttrList) && CollectionUtils.isNotEmpty(colGroupAttrList)) || CollectionUtils.isNotEmpty(colGroupAttrList)){
            //设置了行列 、 列
            getRowAndColData(colMap,rowKeyList,sumMap,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
        }else if(CollectionUtils.isNotEmpty(rowGroupAttrList)){
            //设置了行
            subTotalRowResult(rowMap,colMap,sum,chartAnalysisDTO,sumMap,yearChainOriginValMap,dataWarningQueryListVO);
        }
    }

    /**
     * 小计-只设置行分组字段时的处理逻辑
     *
     * @param rowMap 行字段容器（只存储第一层，多个字段嵌套在第一层的childMap中）
     * @param colMap 列字段容器 (只存储第一层，多个字段嵌套在第一层的childMap中)
     * @param sum 0-小计 1-总计 2-小计&总计
     * @param chartAnalysisDTO 入参实体
     * @param sumMap 存储总的数据
     * @param yearChainOriginValMap 同环比实体
     * @param dataWarningQueryListVO 数据预警实体
     * @author zyy
     * @date 2022/8/22
     * @version v1.0
     */
    private void subTotalRowResult(Map<String, ChartStatisticsPojo> rowMap, Map<String, ChartStatisticsPojo> colMap, Integer sum, ChartAnalysisDTO chartAnalysisDTO, Map<String, Map<String, ChartStatisticsPojo>> sumMap, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO) {
        int index = 0;
        Map<String,Map<String,String>> subTotalMap = analyzeSubtotal(chartAnalysisDTO);
        for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : rowMap.entrySet()) {
            Map<String, ChartStatisticsPojo> rowSubTotalMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            ChartStatisticsPojo chartStatisticsPojo = new ChartStatisticsPojo();
            chartStatisticsPojo.setParentKey(new StringBuffer());
            setAggValue(stringChartStatisticsPojoEntry.getValue(), sumMap,  chartStatisticsPojo, rowSubTotalMap, yearChainOriginValMap, dataWarningQueryListVO, sum);
            for (Map.Entry<String, ChartStatisticsPojo> chartStatisticsPojoEntry : rowSubTotalMap.entrySet()) {
                String key = chartStatisticsPojoEntry.getKey();
                ChartStatisticsPojo value = chartStatisticsPojoEntry.getValue();
                ChartStatisticsPojo pojo = colMap.get(key);
                if(pojo != null){
                    pojo.getOriginValues().addAll(value.getOriginValues());
                }else {
                    pojo = (ChartStatisticsPojo) CloneUtil.deepClone(value);
                }
                String summaryTotal = "";
                if(subTotalMap.containsKey(stringChartStatisticsPojoEntry.getValue().getParentKey().toString())){
                    summaryTotal = subTotalMap.get(stringChartStatisticsPojoEntry.getValue().getParentKey().toString()).get(chartStatisticsPojoEntry.getKey());
                }
                pojo.getOriginValues().add(summaryTotal);
                boolean setWarningFlag = (++index == rowMap.entrySet().size());
                // 处理预警数据
                handleDataWarningData(pojo.getSummaryFieldAttrPojo(), dataWarningQueryListVO,pojo.getOriginValues(), pojo,setWarningFlag, sum);
                // 格式化
                List<String> sumList = new ArrayList<>(pojo.getOriginValues());
                FieldAttrPojo summaryFieldAttrPojo = pojo.getSummaryFieldAttrPojo();
                ckResultHelp.getNumFormat(summaryFieldAttrPojo, sumList);
                //用格式化后的数据替换掉原来的值
                pojo.setValues(sumList);
                colMap.put(key,pojo);
            }
        }
    }

    /**
     * 统计表源数据组装（小计值在组装时获取）
     *
     * @param colMap 列分组字段容器
     * @param rowKeyList 行数据数组（每个行字段的值拼到一起）
     * @param sumMap 存储总的数据
     * @param rowMap 行分组字段容器
     * @param sum 0-小计 1-总计 2小计&总计
     * @param yearChainOriginValMap  同环比实体
     * @param dataWarningQueryListVO 数据预警实体
     * @param chartAnalysisDTO 入参实体
     * @author zyy
     * @date 2022/8/22
     * @version v1.0
     */
    private void getRowAndColData(Map<String, ChartStatisticsPojo> colMap, List<String> rowKeyList, Map<String, Map<String, ChartStatisticsPojo>> sumMap, Map<String, ChartStatisticsPojo> rowMap, Integer sum, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO, ChartAnalysisDTO chartAnalysisDTO) {
        for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : colMap.entrySet()) {
            ChartStatisticsPojo chartStatisticsPojo =  stringChartStatisticsPojoEntry.getValue();
            StringBuffer parentKey = chartStatisticsPojo.getParentKey();
            if(parentKey == null){
                parentKey = new StringBuffer();
            }
            parentKey.append(chartStatisticsPojo.getOriginValue()).append("|");
            chartStatisticsPojo.setParentKey(parentKey);
            setColChild(chartStatisticsPojo,rowKeyList,sumMap,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
        }
    }

    private void rebuildColFieldSort(List<FieldAttrPojo> fieldAttrPojoList, Map<String, ChartStatisticsPojo> colMap) {
        //列分组字段数组为空，或者第一个不是下拉框字段
        if(CollectionsUtil.isEmpty(fieldAttrPojoList) || !FieldTypeEnum.isReOrder4Combo(fieldAttrPojoList.get(0).getFieldType())){
            return;
        }
        FieldAttrPojo fieldAttrPojo = fieldAttrPojoList.get(0);
        List<ItemPoJo> items = fieldAttrPojo.getItems();
        if(CollectionsUtil.isEmpty(items)){
            //防空
            return;
        }
        //下拉单选的顺序
        List<String> itemValueList = items.stream().map(poJo -> String.valueOf(poJo.getValue())).collect(Collectors.toList());
        //初始化数据中转容器
        Map<String,ChartStatisticsPojo> rebuildColMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        String attr = fieldAttrPojo.getAttr();
        for (String item : itemValueList) {
            String key = attr + "&" + item;
            if(colMap.containsKey(key)){
                rebuildColMap.put(key,colMap.get(key));
                colMap.remove(key);
            }
        }
        //将colMap中剩余的匹配不到的key，或者""的数据放到最后。 先是"" 在是匹配不到的key（保持跟sql中处理的一致）
        if(colMap.size() > 0){
            for (Map.Entry<String, ChartStatisticsPojo> pojoEntry : colMap.entrySet()) {
                String entryKey = pojoEntry.getKey();
                String[] split = entryKey.split("&");
                //先放""
                if(split.length == 1 && attr.equals(split[0])){
                    rebuildColMap.put(entryKey,pojoEntry.getValue());
                    colMap.remove(entryKey);
                    //""类型分组只有一个
                    break;
                }
            }
            //剩下的就是匹配不到下拉单选值的key，直接放到最后
            rebuildColMap.putAll(colMap);
            colMap.clear();
        }
        //最外层拿不到return的中转容器，也不想改动方法的返回值，这里选择覆盖原对象的值
        colMap.putAll(rebuildColMap);
    }


    /**
     * 构建总计（最下面一行）
     * @param chartAnalysisDTO
     * @param chartEntity
     * @param aggFieldMap
     * @param resultTableVO
     * @param rowGroupAttrList
     * @param colGroupAttrList
     * @param summaryAttrMap
     * @param colMap
     */
    private void summaryStructure(ChartAnalysisDTO chartAnalysisDTO, ChartEntity chartEntity, Map<String, AggFieldPojo> aggFieldMap, ResultTableVO resultTableVO, List<FieldAttrPojo> rowGroupAttrList, List<FieldAttrPojo> colGroupAttrList, Map<String, FieldAttrPojo> summaryAttrMap, Map<String, ChartStatisticsPojo> colMap) {
        JSONArray sumJsonArray = chartAnalysisDTO.getSumJsonArray();
        List<String> newSummaryList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String,JSONObject> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //保留该容器，部分情况还是要在内存中获取数据
        Map<String, Double> totalMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //新增容器，存储着从数据库中获取的数据
        JSONArray totalJsonArray = chartAnalysisDTO.getTotalOfTotalJsonArray();
        for (int dataI = 0; dataI < sumJsonArray.size(); dataI++) {
            JSONObject resultObj = sumJsonArray.getJSONObject(dataI);
            if(resultObj == null){
                continue;
            }
            StringBuilder outKeyBuffer = new StringBuilder();
            if(CollectionsUtil.isNotEmpty(colGroupAttrList)){
                for (int i = 0; i < colGroupAttrList.size(); i++) {
                    FieldAttrPojo fieldAttrPojo = colGroupAttrList.get(i);
                    String esValue;
                    if (!Objects.isNull(fieldAttrPojo.getValue())) {
                        // 钻取之后获取转化信息特殊处理
                        esValue = fieldAttrPojo.getValue().toString();
                    } else {
                        // 获取转化信息
                        esValue = getEsValue(resultObj, chartEntity, fieldAttrPojo, fieldAttrPojo.getAttr(), fieldAttrPojo.getFieldType());
                    }
                    outKeyBuffer.append(esValue).append("|");
                }
            }else {
                //只有列为空的时候才取行
                if(CollectionsUtil.isNotEmpty(rowGroupAttrList)){
                    for (int i = 0; i < rowGroupAttrList.size(); i++) {
                        FieldAttrPojo fieldAttrPojo = rowGroupAttrList.get(i);
                        String esValue;
                        if (!Objects.isNull(fieldAttrPojo.getValue())) {
                            // 钻取之后获取转化信息特殊处理
                            esValue = fieldAttrPojo.getValue().toString();
                        } else {
                            // 获取转化信息
                            esValue = getEsValue(resultObj, chartEntity, fieldAttrPojo, fieldAttrPojo.getAttr(), fieldAttrPojo.getFieldType());
                        }
                        outKeyBuffer.append(esValue).append("|");
                    }
                }
            }
            map.put(outKeyBuffer.toString(),resultObj);
            for (String s : aggFieldMap.keySet()) {
                Double aDouble = totalMap.get(s);
                aDouble = Arith.add( aDouble == null ? 0: aDouble , resultObj.getDouble(s) == null ? 0 :resultObj.getDouble(s));
                totalMap.put(s, aDouble );
            }
        }
        //用户手动设置汇总字段的话在这里调整colMap的顺序
        sortColMap(colGroupAttrList,new HashMap<>(map),colMap,chartAnalysisDTO.getChartResultPojo().getSortStatisticsMap(),aggFieldMap);
        setSummary(new ArrayList<>(colMap.values()),newSummaryList,map, aggFieldMap, summaryAttrMap);
        for (String s : aggFieldMap.keySet()) {
            AggFieldPojo aggFieldPojo =  aggFieldMap.get(s);
            String attr = aggFieldPojo.getAttr();
            String aggName = attr + "&" + aggFieldPojo.getFieldType() + "&" + aggFieldPojo.getIndex();
            FieldAttrPojo fieldAttrPojo = summaryAttrMap.get(aggName);
            int accuracy = fieldAttrPojo.getAccuracy() == null ? 0 : fieldAttrPojo.getAccuracy();
            Integer percentUsed = fieldAttrPojo.getPercentUsed();
            Integer groupingUsed = fieldAttrPojo.getGroupingUsed() == null ? fieldAttrPojo.getAmountFlag() : fieldAttrPojo.getGroupingUsed();
            Integer numFormat = fieldAttrPojo.getNumFormat();
            NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(numFormat);
            String unit = numFormatEnum.getNoYuanUnit();
            String formatVal = "";
            // 同环比暂不计算列汇总
            if(AdvancedComputingFirstEnum.noneYearChain(aggFieldPojo.getAdvancedComputing())){
                String newVal = "";
                if(CollectionsUtil.isEmpty(totalJsonArray) && !totalMap.isEmpty() && totalMap.get(s)!=null){
                    //从内存容器取数据
                    newVal = String.valueOf(ChartResultUtil.formatVal4Num(new BigDecimal(totalMap.get(s).toString()), numFormatEnum, FieldAnalysisHelp.isPercentUsedOfAccuracy(percentUsed,accuracy)));
                }else{
                    //从数据库容器取数据
                    newVal = getTotalOfTotalVal(totalJsonArray,s,numFormatEnum,percentUsed,accuracy);
                }
                formatVal = attrDecimalPrecisionHelper.getNumberFormat(newVal, accuracy, groupingUsed, percentUsed);
                if (StringUtil.isNotEmpty(unit)) {
                    formatVal += unit;
                }
            }
            newSummaryList.add(formatVal);
        }
        resultTableVO.setSummary(newSummaryList);
    }

    /**
     * 获取总计的总计值
     *
     * @param totalJsonArray  总记的总计的结果数组
     * @param attr 汇总字段attr
     * @param numFormatEnum 汇总字段的数值格式
     * @return java.lang.String
     * @author zyy
     * @date 2022/8/26
     * @version v1.0
     */
    private String getTotalOfTotalVal(JSONArray totalJsonArray,String attr,NumFormatEnum numFormatEnum, Integer percentUsed,Integer accuracy) {
        String resultStr = "";
        if(CollectionsUtil.isEmpty(totalJsonArray)){
            return resultStr;
        }
        //jsonObject中只会有一个对应的attr
        JSONObject jsonObject = totalJsonArray.getJSONObject(0);
        if(jsonObject.containsKey(attr) && StringUtils.isNotBlank(jsonObject.getString(attr))){
            resultStr = String.valueOf(ChartResultUtil.formatVal4Num(new BigDecimal(jsonObject.getString(attr)), numFormatEnum,FieldAnalysisHelp.isPercentUsedOfAccuracy(percentUsed,accuracy)));
        }
        return resultStr;
    }

    /**
     * 用户手动对汇总字段进行排序时，调整最下方总计值的顺序
     *
     * @param colGroupAttrList 列分组字段数组
     * @param map   key：每层列的值拼|    value：对应列的总计值
     * @param colMap 每个最外层列字段与每行数据的映射容器
     * @param sortStatisticsMap  排序字段
     * @param aggFieldMap 汇总字段
     * @author zyy
     * @date 2022/9/6
     * @version v1.0
     */
    private void sortColMap(List<FieldAttrPojo> colGroupAttrList, Map<String, JSONObject> map, Map<String, ChartStatisticsPojo> colMap, Map<String, String> sortStatisticsMap, Map<String, AggFieldPojo> aggFieldMap) {
        if(sortStatisticsMap == null || sortStatisticsMap.size() == 0 || CollectionUtils.isEmpty(colGroupAttrList) || map.size() == 0){
            return;
        }
        //排序字段是否为汇总字段
        String summaryKey = sortBySummaryField(sortStatisticsMap,aggFieldMap);
        if(StringUtils.isBlank(summaryKey)){
            return;
        }
        //解析汇总字段的key，排序方式
        String[] split = summaryKey.split("-");
        String sumKey = split[0];
        String orderBy = split[1];
        //只处理最外层列字段
        FieldAttrPojo fieldAttrPojo = colGroupAttrList.get(0);
        String attr = fieldAttrPojo.getAttr();
        //初始化排序后的容器
        Map<String,ChartStatisticsPojo> sortColMap =  new LinkedHashMap<>();
        //对数据进行排序
        Map<String,BigDecimal> tmpMap = new HashMap<>();
        for (Map.Entry<String, JSONObject> entry : map.entrySet()) {
            String key = entry.getKey();
            JSONObject jsonObject = entry.getValue();
            String colKey = attr + "&" + key.substring(0,key.indexOf("|"));
            if (EsHelper.isDateTimeByFieldType(fieldAttrPojo.getFieldType())) {
                colKey = colKey + "&" + fieldAttrPojo.getDateGroupType();
            }
            String varStr = jsonObject.getString(sumKey);
            if(StringUtils.isBlank(varStr)){
                varStr = "0";
            }
            BigDecimal sumVar = new BigDecimal(varStr);
            if(tmpMap.containsKey(colKey)){
                BigDecimal decimal = tmpMap.get(colKey).add(sumVar);
                tmpMap.put(colKey,decimal);
            }else{
                tmpMap.put(colKey,sumVar);
            }
        }
        List<Map.Entry<String,BigDecimal>> list = new ArrayList<>(tmpMap.entrySet());
        list.sort(new Comparator<Map.Entry<String, BigDecimal>>() {
            @Override
            public int compare(Map.Entry<String, BigDecimal> o1, Map.Entry<String, BigDecimal> o2) {
                int num;
                if ("desc".equals(orderBy)) {
                    //降序
                    num = o2.getValue().intValue() - o1.getValue().intValue();
                } else {
                    //升序
                    num = o1.getValue().intValue() - o2.getValue().intValue();
                }
                return num;
            }
        });
        //将排序后的数据覆盖回colMap中
        for (Map.Entry<String, BigDecimal> stringBigDecimalEntry : list) {
            String key = stringBigDecimalEntry.getKey();
            sortColMap.put(key,colMap.get(key));
        }
        if(colMap.containsKey("")){
            sortColMap.put("",colMap.get(""));
        }
        colMap.clear();
        colMap.putAll(sortColMap);
    }

    private String sortBySummaryField(Map<String, String> sortStatisticsMap, Map<String, AggFieldPojo> aggFieldMap) {
        //判断第一个排序字段是否为汇总字段（目前统计表可以对多个汇总字段进行排序）
        String orderKey = "";
        String orderBy = "";
        for (String key : sortStatisticsMap.keySet()) {
            orderKey = key;
            orderBy = sortStatisticsMap.get(key);
            break;
        }
        for (Map.Entry<String, AggFieldPojo> pojoEntry : aggFieldMap.entrySet()) {
            AggFieldPojo aggFieldPojo = pojoEntry.getValue();
            String aggKey = aggFieldPojo.getAttr() + "&" + aggFieldPojo.getFieldType();
            //计数字段会额外拼接formId
            if(orderKey.contains("count")){
                //这里兼容数据集- 数据集没有formId
                if(Objects.equals(aggKey + "&" + XbbConstant.UNDEFINED,orderKey)){
                    return pojoEntry.getKey()+"-"+orderBy;
                }
                aggKey = aggKey + "&" + aggFieldPojo.getFormId();
            }
            if (Objects.equals(aggKey,orderKey)){
                return pojoEntry.getKey()+"-"+orderBy;
            }
        }
        return "";
    }


    /**
     * 设置列分组和数据
     * @param stringChartStatisticsPojoEntry 列分组pojo
     * @param keyList  行分组key
     * @param sumMap 数据源
     * @param yearChainOriginValMap 同环比原始值map，key:日期时间戳，val：原始统计值
     */
    private void setColChild(ChartStatisticsPojo stringChartStatisticsPojoEntry, List<String> keyList, Map<String, Map<String, ChartStatisticsPojo>> sumMap, Map<String, ChartStatisticsPojo> rowMap, Integer sum, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO, ChartAnalysisDTO chartAnalysisDTO) {
        Map<String, ChartStatisticsPojo> childMap = stringChartStatisticsPojoEntry.getChildMap();
        if(childMap != null && !childMap.isEmpty()){
            //利用下一级的mapValues设置上级的childList
            Collection<ChartStatisticsPojo> values = childMap.values();
            List<ChartStatisticsPojo> child = (List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(values));
            stringChartStatisticsPojoEntry.setChild(child);
            for (ChartStatisticsPojo chartStatisticsPojo : stringChartStatisticsPojoEntry.getChild()) {
                StringBuffer innerParentKey = chartStatisticsPojo.getParentKey();
                if(innerParentKey == null){
                    innerParentKey = new StringBuffer();
                }
                innerParentKey.append(stringChartStatisticsPojoEntry.getParentKey()).append(chartStatisticsPojo.getOriginValue()).append("|");
                chartStatisticsPojo.setParentKey(innerParentKey);
                if(chartStatisticsPojo.getChildMap()!=null && !chartStatisticsPojo.getChildMap().isEmpty()){
                    chartStatisticsPojo.setChild((List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(chartStatisticsPojo.getChildMap().values())));
                    setColChild(chartStatisticsPojo,keyList,sumMap,rowMap,sum, yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
                }else {
                    setRowColValues(keyList, sumMap, chartStatisticsPojo,rowMap,sum, yearChainOriginValMap,dataWarningQueryListVO, chartAnalysisDTO);
                }
            }
        }else {
            setRowColValues(keyList, sumMap, stringChartStatisticsPojoEntry,rowMap,sum,yearChainOriginValMap,dataWarningQueryListVO,chartAnalysisDTO);
        }
    }


    /**
     * 设置数据(区分情况是否有行分组)
     * @param rowKeyList  行分组key
     * @param sumMap 数据源
     * @param chartStatisticsPojo
     * @param sum 汇总方式  0小计、1总计
     * @param yearChainOriginValMap 同环比原始值map，key:日期时间戳，val：原始统计值
     */
    private void setRowColValues(List<String> rowKeyList, Map<String, Map<String, ChartStatisticsPojo>> sumMap, ChartStatisticsPojo chartStatisticsPojo, Map<String, ChartStatisticsPojo> rowMap, Integer sum, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO, ChartAnalysisDTO chartAnalysisDTO) {
        Map<String, ChartStatisticsPojo> innerSumMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(CollectionsUtil.isNotEmpty(rowKeyList)){
            // 小计处理
            if(Objects.equals(sum,0)  || Objects.equals(sum,2)){
                Map<String,Map<String,String>> subTotalMap = analyzeSubtotal(chartAnalysisDTO);
                String colKey = chartStatisticsPojo.getParentKey().toString();
                for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : rowMap.entrySet()) {
                    String subTotalKey = colKey + stringChartStatisticsPojoEntry.getValue().getParentKey().toString();
                    Map<String, ChartStatisticsPojo> rowSubTotalMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    setAggValue(stringChartStatisticsPojoEntry.getValue(), sumMap, chartStatisticsPojo, rowSubTotalMap, yearChainOriginValMap,dataWarningQueryListVO,sum);
                    int index = 0;
                    boolean setWarningFlag = false;
                    for (Map.Entry<String, ChartStatisticsPojo> chartStatisticsPojoEntry : rowSubTotalMap.entrySet()) {
                        if (++index == rowSubTotalMap.entrySet().size()){
                            setWarningFlag = true;
                        }
                        String key = chartStatisticsPojoEntry.getKey();
                        ChartStatisticsPojo value = chartStatisticsPojoEntry.getValue();
                        ChartStatisticsPojo pojo = innerSumMap.get(key);
                        List<String> originValues = value.getOriginValues();
                        if(pojo != null){
                            pojo.getOriginValues().addAll(originValues);
                            // 格式化
                            List<String> originValuesCopy = new ArrayList<>(originValues);
                            ckResultHelp.getNumFormat(pojo.getSummaryFieldAttrPojo(), originValuesCopy);
                            pojo.getValues().addAll(originValuesCopy);
                        } else {
                            pojo = (ChartStatisticsPojo) CloneUtil.deepClone(value);
                        }
                        String summaryTotal = "";
                        if(subTotalMap.containsKey(subTotalKey)){
                            summaryTotal = subTotalMap.get(subTotalKey).get(chartStatisticsPojoEntry.getKey());
                        }
                        pojo.getOriginValues().add(summaryTotal);
                        // 处理预警数据
                        handleDataWarningData(pojo.getSummaryFieldAttrPojo(),dataWarningQueryListVO,pojo.getOriginValues(), pojo,setWarningFlag,sum);
                        // 格式化
                        List<String> sumTotalList = Arrays.asList(summaryTotal);
                        ckResultHelp.getNumFormat(pojo.getSummaryFieldAttrPojo(), sumTotalList);
                        pojo.getValues().addAll(sumTotalList);
                        innerSumMap.put(key,pojo);
                    }
                }
            }else {
                for (String rowKey : rowKeyList) {
                    setColValues(sumMap, chartStatisticsPojo, innerSumMap, rowKey, yearChainOriginValMap);
                }
            }
        }else {
            setColValues(sumMap, chartStatisticsPojo, innerSumMap, "", yearChainOriginValMap);
        }
        chartStatisticsPojo.setChild((List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(innerSumMap.values())));
    }

    /**
     * 解析小计数据，并拼装指定格式的数据 【（列/行的值拼成的key  定位到某行） -> 【(当前行汇总字段key) -> （汇总字段值）】】
     *
     * @param chartAnalysisDTO 请求入参实体
     * @return java.util.Map<java.lang.String,java.util.Map<java.lang.String,java.lang.String>>
     * @author zyy
     * @date 2022/10/8
     * @version v1.0
     */
    private Map<String,Map<String,String>> analyzeSubtotal(ChartAnalysisDTO chartAnalysisDTO) {
        Map<String,Map<String,String>> resultMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONArray subTotalJsonArray = chartAnalysisDTO.getSubTotalJsonArray();
        if(CollectionUtils.isEmpty(subTotalJsonArray)){
            return resultMap;
        }

        //获取行、列分组字段
        ChartEntity chartEntity = chartAnalysisDTO.getChartEntity();
        List<FieldAttrPojo> rowAttrList = JSONArray.parseArray(chartEntity.getRowGroupAttr().toJSONString(), FieldAttrPojo.class);
        List<FieldAttrPojo> colAttrList = JSONArray.parseArray(chartEntity.getColGroupAttr().toJSONString(), FieldAttrPojo.class);
        //行分组只取到第一个（走到该方法一定会有行分组）
        FieldAttrPojo fieldAttrPojo = rowAttrList.get(0);
        String rowAttr = fieldAttrPojo.getAttr();
        Map<String, AggFieldPojo> aggFieldMap = chartAnalysisDTO.getAggFieldMap();

        for (int i = 0; i < subTotalJsonArray.size(); i++) {
            JSONObject jsonObject = subTotalJsonArray.getJSONObject(i);
            StringBuilder sb = new StringBuilder();
            if(CollectionUtils.isNotEmpty(colAttrList)){
                //列分组需要拼到最后一个
                for (FieldAttrPojo attrPojo : colAttrList) {
                    String attr = attrPojo.getAttr();
                    String colKey;
                    if (!Objects.isNull(attrPojo.getValue())) {
                        // 钻取之后获取转化信息特殊处理
                        colKey = attrPojo.getValue().toString();
                    } else {
                        // 获取转化信息
                        colKey = getEsValue(jsonObject, chartEntity, attrPojo, attr, attrPojo.getFieldType());
                    }
                    sb.append(colKey).append("|");
                }
            }
            String rowKey;
            if (!Objects.isNull(fieldAttrPojo.getValue())) {
                // 钻取之后获取转化信息特殊处理
                rowKey = fieldAttrPojo.getValue().toString();
            } else {
                // 获取转化信息
                rowKey = getEsValue(jsonObject, chartEntity, fieldAttrPojo, rowAttr, fieldAttrPojo.getFieldType());
            }
            sb.append(rowKey).append("|");
            //小计所在行列对应的key
            String key = sb.toString();

            //组装行列对应的小计值
            Map<String,String> aggValueMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (String aggKey : aggFieldMap.keySet()) {
                String aggValue = getEsValue(jsonObject, chartEntity, fieldAttrPojo, aggKey, aggFieldMap.get(aggKey).getFieldType());
                AggFieldPojo aggFieldPojo = aggFieldMap.get(aggKey);
                String aggValueKey = aggFieldPojo.getAttr() + "&" + aggFieldPojo.getFieldType() + "&" + aggFieldPojo.getIndex();
                aggValueMap.put(aggValueKey,aggValue);
            }
            resultMap.put(key,aggValueMap);
        }
        return resultMap;
    }


    /**
     * 从行分组开始设置层级结果
     * @param stringChartStatisticsPojoEntry 列分组pojo
     * @param sumMap 数据源
     * @param chartStatisticsPojo
     * @param innerSumMap 结果集
     * @param yearChainOriginValMap 同环比原始值map，key:日期时间戳，val：原始统计值
     */
    private void setAggValue(ChartStatisticsPojo stringChartStatisticsPojoEntry, Map<String, Map<String, ChartStatisticsPojo>> sumMap, ChartStatisticsPojo chartStatisticsPojo, Map<String, ChartStatisticsPojo> innerSumMap, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, DataWarningQueryListVO dataWarningQueryListVO,Integer sum) {
        Map<String, ChartStatisticsPojo> childMap = stringChartStatisticsPojoEntry.getChildMap();
        if(childMap != null && !childMap.isEmpty()){
            //利用下一级的mapValues设置上级的childList
            Collection<ChartStatisticsPojo> values = childMap.values();
            List<ChartStatisticsPojo> child = (List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(values));
            stringChartStatisticsPojoEntry.setChild(child);
            //因为这里是用childMap不会冗余，前面设置的child
            for (ChartStatisticsPojo rolePojo : stringChartStatisticsPojoEntry.getChild()) {
                StringBuffer innerParentKey = rolePojo.getParentKey();
                if(innerParentKey == null){
                    innerParentKey = new StringBuffer();
                }
                innerParentKey.append(stringChartStatisticsPojoEntry.getParentKey()).append(rolePojo.getOriginValue()).append("|");
                rolePojo.setParentKey(innerParentKey);
                if(rolePojo.getChildMap()!=null && !rolePojo.getChildMap().isEmpty()){
                    rolePojo.setChild((List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(rolePojo.getChildMap().values())));
                    setAggValue(rolePojo,sumMap,  chartStatisticsPojo,innerSumMap, yearChainOriginValMap,dataWarningQueryListVO,sum);
                }else {
                    setColValues(sumMap, chartStatisticsPojo, innerSumMap, rolePojo.getParentKey().toString(), yearChainOriginValMap);
                }
            }
        }else {
            setColValues(sumMap, chartStatisticsPojo, innerSumMap, stringChartStatisticsPojoEntry.getParentKey().toString(), yearChainOriginValMap);
        }
    }

    /**
     * 处理统计表预警数据
     */
    private void handleDataWarningData(FieldAttrPojo summaryFieldAttrPojo, DataWarningQueryListVO dataWarningQueryListVO,List<String> originValues,ChartStatisticsPojo pojo,boolean setWarningDataFlag,int sum){
        if (!setWarningDataFlag){
            return;
        }
        // 统计表数据预警start
        List<WarningValuePojo> warningValues = new ArrayList<>();
        String originalAttr = summaryFieldAttrPojo.getOriginalAttr();
        String dwKey = summaryFieldAttrPojo.getAttr() + "&" + summaryFieldAttrPojo.getFormId();
        if (Objects.isNull(dwKey)){
            dwKey = originalAttr + "&" + summaryFieldAttrPojo.getFormId();
        }

        // 为了防止一个当前预警数据同时触发多个预警设置，不知道选那个，取这个预警数据到预警设置最接近的数据
        Map<String,Object> distinctMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        int warningIndex = 0;
        if (Objects.nonNull(dataWarningQueryListVO) && CollectionUtils.isNotEmpty(dataWarningQueryListVO.getDataWarningQueryVOList())){
            for (DataWarningQueryVO item : dataWarningQueryListVO.getDataWarningQueryVOList()) {
                // 统计表有多值
                List<DwTriggerConditionPojo> triggerConditionList = item.getTriggerCondition().toJavaList(DwTriggerConditionPojo.class);
                DwTriggerConditionPojo triggerConditionPojo;
                if (CollectionUtils.isNotEmpty(triggerConditionList)){
                    triggerConditionPojo = triggerConditionList.get(0);
                    if(!dwKey.contains(triggerConditionPojo.getId())){
                        continue;
                    }
                }else {
                    continue;
                }
                int valueIndex = 0;
                for (int i = 0; i < originValues.size(); i++) {
                    String value = originValues.get(i);
                    Boolean flag = true;
                    if (Objects.equals(sum,0)){
                        if ( i%2 == 1 ){
                            flag = false;
                        }
                    }
                    if (chartResultHelp.checkIsTrigger(item.getTriggerCondition(), value)) {
                        WarningValuePojo warningValuePojo = new WarningValuePojo();
                        warningValuePojo.setValue(value);
                        warningValuePojo.setColor(item.getColor());
                        warningValuePojo.setWarningFlag(flag);
                        if (chartResultHelp.isCover(item.getTriggerCondition(), value,distinctMap,valueIndex)){
                            if ((warningValues.size()-1) >= valueIndex){
                                warningValues.set(valueIndex,warningValuePojo);
                                if (flag){
                                    dataWarningQueryListVO.setWarningFlag(true);
                                }
                            }else {
                                warningValues.add(warningValuePojo);
                                if (flag){
                                    dataWarningQueryListVO.setWarningFlag(true);
                                }
                            }
                        }else if (warningValues.size() < originValues.size()){
                            warningValues.add(warningValuePojo);
                            if (flag){
                                dataWarningQueryListVO.setWarningFlag(true);
                            }
                        }
                    }else if (warningIndex == 0){
                        WarningValuePojo warningValuePojo = new WarningValuePojo();
                        warningValuePojo.setValue(value);
                        warningValuePojo.setWarningFlag(false);
                        warningValues.add(warningValuePojo);
                    }
                    valueIndex++;
                }
                warningIndex ++;
            }
        }
        ckResultHelp.getNumFormat4Dw(summaryFieldAttrPojo, warningValues);
        pojo.setWarningValues(warningValues);
        // 统计表数据预警end
    }

    /**
     * 设置数据(这个方法在最后一个层级，有值的设置值，没有值的给引号)
     * @param sumMap 数据源
     * @param chartStatisticsPojo 列分组pojo
     * @param innerSumMap 结果集
     * @param rowKey  行分组的key
     * @param yearChainOriginValMap 同环比原始值map，key:日期时间戳，val：原始统计值
     */
    private void setColValues(Map<String, Map<String, ChartStatisticsPojo>> sumMap, ChartStatisticsPojo chartStatisticsPojo, Map<String, ChartStatisticsPojo> innerSumMap, String rowKey, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap) {
        String colKey = chartStatisticsPojo.getParentKey().toString();
        Map<String, ChartStatisticsPojo> innerMap = sumMap.get(rowKey + colKey);
        if(innerMap !=null && !innerMap.isEmpty()) {
            for (Map.Entry<String, ChartStatisticsPojo> sumInnerEntity : innerMap.entrySet()) {
                String key = sumInnerEntity.getKey();
                ChartStatisticsPojo summaryStatisticsPojo = sumInnerEntity.getValue();
                FieldAttrPojo summaryFieldAttrPojo = summaryStatisticsPojo.getSummaryFieldAttrPojo();
                List<String> innerOriginValues = summaryStatisticsPojo.getOriginValues();
                // 避免对原对象内的值产生影响
                List<String> innerOriginValuesCopy = new ArrayList<>(innerOriginValues);
                if(innerSumMap.containsKey(key)) {
                    ChartStatisticsPojo pojo = innerSumMap.get(key);
                    if(CollectionsUtil.isNotEmpty(innerOriginValuesCopy)) {
                        List<String> originValues = pojo.getOriginValues();
                        if (CollectionUtils.isEmpty(originValues)) {
                            continue;
                        }
                        // 同环比处理
                        if (!yearChainOriginValMap.isEmpty()) {
                            String oldVal = getOldVal4StatisticsTable(rowKey, colKey, yearChainOriginValMap, key, summaryStatisticsPojo);
                            // innerOriginValues里面永远只有一个值，直接get(0)
                            String value = chartResultHelp.getYearChainValue(summaryFieldAttrPojo, oldVal, innerOriginValuesCopy.get(0));
                            innerOriginValuesCopy.clear();
                            innerOriginValuesCopy.add(value);
                        }
                        originValues.addAll(innerOriginValuesCopy);
                        // 格式化
                        ckResultHelp.getNumFormat(summaryFieldAttrPojo, innerOriginValuesCopy);
                        pojo.getValues().addAll(innerOriginValuesCopy);
                    }
                } else {
                    // 第一行数据的时候会走到这
                    List<String> originValues = summaryStatisticsPojo.getOriginValues();
                    if (CollectionUtils.isEmpty(originValues)) {
                        continue;
                    }
                    // 避免对原对象内的值产生影响
                    List<String> originValuesCopy = new ArrayList<>(originValues);
                    // 同环比处理
                    if (!yearChainOriginValMap.isEmpty()) {
                        String oldVal = getOldVal4StatisticsTable(rowKey, colKey, yearChainOriginValMap, key, summaryStatisticsPojo);
                        // originValues里面永远只有一个值，直接get(0)
                        String value = chartResultHelp.getYearChainValue(summaryFieldAttrPojo, oldVal, originValuesCopy.get(0));
                        originValuesCopy.clear();
                        originValuesCopy.add(value);
                        summaryStatisticsPojo.setOriginValues(originValuesCopy);
                    }
                    // 格式化
                    List<String> values = new ArrayList<>(originValuesCopy);
                    ckResultHelp.getNumFormat(summaryFieldAttrPojo, values);
                    summaryStatisticsPojo.setValues(values);
                    innerSumMap.put(key, summaryStatisticsPojo);
                }
            }
        } else {
            //没有值的时候放引号“”
            for (Map.Entry<String, Map<String, ChartStatisticsPojo>> stringMapEntry : sumMap.entrySet()) {
                Map<String, ChartStatisticsPojo> emptyInnerMap = stringMapEntry.getValue();
                //新加了列分组下拉字段类型调整顺序的需求，这里不能直接拿sumMap中对象来用，会造成重复数据。因此需要获取新的对象。
                Map<String, ChartStatisticsPojo> deepClone = (Map<String, ChartStatisticsPojo>) CloneUtil.deepClone(emptyInnerMap);
                for (Map.Entry<String, ChartStatisticsPojo> sumInnerEntity : deepClone.entrySet()) {
                    String key = sumInnerEntity.getKey();
                    ChartStatisticsPojo value = sumInnerEntity.getValue();
                    List<String> innerValues = new ArrayList<>(1);
                    innerValues.add("");
                    if(innerSumMap.containsKey(key)){
                        ChartStatisticsPojo pojo = innerSumMap.get(key);
                        pojo.getOriginValues().addAll(innerValues);
                        pojo.getValues().addAll(innerValues);
                    } else {
                        value.setOriginValues(innerValues);
                        List<String> values = new ArrayList<>(innerValues);
                        value.setValues(values);
                        innerSumMap.put(key, value);
                    }
                }
                //只是为了填空占住位置
                break;
            }
        }
    }

    /**
     * 预设行列分组
     * @param drillField               钻取的标识
     * @param drillResultChartInfoPojo 某一张图的总钻取信息pojo，包含总筛选条件、钻取层级信息和钻取信息map
     * @param rowOrColGroupAttrList    行列分组字段
     * @param rowOrColMap              行列数据载体返回行数据载体返回
     * @param resultObj                查询结果
     * @param chartAnalysisDTO         参数
     */
    private void setRowOrColMap(String drillField, DrillResultChartInfoPojo drillResultChartInfoPojo, List<FieldAttrPojo> rowOrColGroupAttrList, Map<String, ChartStatisticsPojo> rowOrColMap, JSONObject resultObj, ChartAnalysisDTO chartAnalysisDTO, ChartEntity chartEntity, Map<String, Map<String, String>> attrLinkMap) throws XbbException {
        if(CollectionsUtil.isNotEmpty(rowOrColGroupAttrList)){
            // 钻取的属性条件集合（图表需要拼接上以及钻取的符号）
            List<FieldAttrPojo> conditionToTableList = getConditionToTableList(drillField, drillResultChartInfoPojo);
            for (int j = 0; j < rowOrColGroupAttrList.size(); j++) {
                FieldAttrPojo fieldAttrPojo = rowOrColGroupAttrList.get(j);
                String attr = fieldAttrPojo.getAttr();
                String esValue;
                // 行、列数据格式化
                Map<String, String> analysisMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Integer fieldType = fieldAttrPojo.getFieldType();
                if (!Objects.isNull(fieldAttrPojo.getValue()) && StringUtil.isNotEmpty(fieldAttrPojo.getValueText())) {
                    // 钻取之后获取转化信息特殊处理
                    esValue = fieldAttrPojo.getValue().toString();
                } else {
                    // 获取转化信息
                    esValue = getEsValue(resultObj, chartEntity, fieldAttrPojo, attr, fieldType);
                    resultObj.put(attr, esValue);
                    analysisMap = valueListAnalysis(fieldAttrPojo, Collections.singletonList(esValue), chartAnalysisDTO.getChartEntity(), chartAnalysisDTO,attrLinkMap);
                }
                String outKey = attr + "&" + esValue;
                // 时间类型字段钻取的时候进行特殊处理，拼上 dateGroupType，用于区别outKey
                if (EsHelper.isDateTimeByFieldType(fieldType)) {
                    outKey = outKey + "&" + fieldAttrPojo.getDateGroupType();
                }
                ChartStatisticsPojo pojo = rowOrColMap.get(outKey);
                if (pojo == null) {
                    pojo = new ChartStatisticsPojo();
                }
                String aggNameAttr = attr;
                boolean isSingle = EsUtil.getSingle(chartEntity);
                if (!isSingle) {
                    aggNameAttr = fieldAttrPojo.getOriginalAttr() == null ? attr : fieldAttrPojo.getOriginalAttr();
                }
                String aggName = aggNameAttr + "&" + fieldType;
                pojo.setOutKey(outKey);
                pojo.setKey(aggName);
                pojo.setOriginValue(esValue);

                // 行、列数据格式化之后的值（不是钻取新增的行列）
                pojo.setValue(chartResultHelp.analysisResultValue(analysisMap,esValue,fieldAttrPojo));
                // 说明是前端在钻取操作时传了value值
                if (StringUtil.isNotEmpty(fieldAttrPojo.getValueText())) {
                    pojo.setValue(fieldAttrPojo.getValueText());
                }
                // 处理上卷符号("-")
                dealDrillTableValueInfo(pojo, fieldAttrPojo, conditionToTableList);
                // 处理钻取匹配信息（处理规则是根据行列分组信息去匹配下钻操作（匹配“+”号））
                dealDrillTableMatchInfo(pojo, fieldAttrPojo, drillResultChartInfoPojo);

                //TODO
                pojo.setDocCount(1L);
                if(j == 0){
                    if(rowOrColMap.get(outKey) != null){
                        continue;
                    }
                    pojo.setChildMap(new LinkedHashMap<>());
                    pojo.setChild(new ArrayList<>());
                    pojo.setParentKey(new StringBuffer());
                    rowOrColMap.put(outKey,pojo);
                }else {
                    Map<String, ChartStatisticsPojo> childMap =  getChildMap(rowOrColMap,0, rowOrColGroupAttrList, resultObj,outKey);
                    if(childMap.containsKey(outKey)){
                        continue;
                    }
                    childMap.put(outKey,pojo);
                }
            }
        }
    }

    private String getEsValue(JSONObject resultObj, ChartEntity chartEntity, FieldAttrPojo fieldAttrPojo, String attr, Integer fieldType) {
        String esValue;
        if (EsHelper.isTeamLogicByFieldType(fieldType, fieldAttrPojo.getBusinessType())) {
            int teamIdx = EsUtil.getTeamIdx(chartEntity, fieldAttrPojo.getFormId());
            StringBuilder stringBuilder = ckResultHelp.getTeamValue(fieldType, teamIdx, resultObj);
            esValue = stringBuilder.toString();
        } else if(FieldTypeEnum.OWNERID.getType().equals(fieldType)){
            esValue = FastJsonHelper.getStringOrDefault(resultObj, attr, "");
            //因为CK和数据集公用，所有不能都用myTeam,ck那边的sql没有团队的as 还是 owner_id
            if(StringUtil.isEmpty(esValue)){
                String team = attr.replace(FieldTypeEnum.OWNERID.getAlias() + "_", XbbConstant.MY_TEAM_MAIN);
                esValue = FastJsonHelper.getStringOrDefault(resultObj, team, "");
            }
            
        } else if (Objects.equals(FieldTypeEnum.ADDRESS.getType(), fieldType) || Objects.equals(FieldTypeEnum.LOCATION.getType(), fieldType)) {
            esValue = FastJsonHelper.getStringOrDefault(resultObj, attr.replaceAll("\\.", "_"), "");
        } else if(Objects.equals(FieldTypeEnum.COMBO_NUM.getType(), fieldType) || Objects.equals(FieldTypeEnum.STAR.getType(), fieldType) || Objects.equals(FieldTypeEnum.CATEGORY_ID.getType(), fieldType)|| Objects.equals(FieldTypeEnum.WORK_ORDER_NODE_STATUS.getType(), fieldType)) {
            //逻辑下拉的处理   星级的key应该也是整数
            Integer intV = FastJsonHelper.getIntegerOrDefault(resultObj, attr, 0);
            if (Objects.nonNull(intV)) {
                esValue = intV.toString();
            }else {
                esValue = "";
            }
        } else {
            esValue = FastJsonHelper.getStringOrDefault(resultObj, attr, "");
            // 秒转毫秒
            esValue = ckResultHelp.handleDate2Ms(fieldType, esValue);
        }
        return esValue;
    }

    /**
     * 获取子集（递归），利用下一级的mapValues设置上级的childList
     * @param rowOrColMap      行列数据载体返回行数据载体返回
     * @param j
     * @param rowGroupAttrList
     * @return
     */
    private Map<String, ChartStatisticsPojo> getChildMap(Map<String, ChartStatisticsPojo> rowOrColMap, int j, List<FieldAttrPojo> rowGroupAttrList,JSONObject resultObj,String outKey) {
        for (Map.Entry<String, ChartStatisticsPojo> stringChartStatisticsPojoEntry : rowOrColMap.entrySet()) {
            String key = stringChartStatisticsPojoEntry.getKey();
            FieldAttrPojo attrPojo = rowGroupAttrList.get(j);
            String attr = attrPojo.getAttr();
            String esValue = FastJsonHelper.getStringOrDefault(resultObj, attr, "");
            if (!Objects.isNull(attrPojo.getValue())) {
                // 钻取之后获取转化信息特殊处理
                esValue = attrPojo.getValue().toString();
            }
            String attrOutKey = attr + "&" + esValue;
            // 时间类型字段钻取的时候进行特殊处理，拼上 dateGroupType，用于区别outKey
            if (EsHelper.isDateTimeByFieldType(attrPojo.getFieldType())) {
                attrOutKey = attrOutKey + "&" + attrPojo.getDateGroupType();
            }
            if(Objects.equals(key,outKey)){
                return rowOrColMap;
            }
            if(Objects.equals(attrOutKey, key)) {
                Map<String, ChartStatisticsPojo> childMap = stringChartStatisticsPojoEntry.getValue().getChildMap();
                if(childMap != null){
                    if(!childMap.isEmpty()){
                        j++;
                        childMap =  getChildMap(childMap, j, rowGroupAttrList,resultObj,outKey);
                    }
                    return childMap;
                }else {
                    childMap = new LinkedHashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    stringChartStatisticsPojoEntry.getValue().setChildMap(childMap);
                    return stringChartStatisticsPojoEntry.getValue().getChildMap();
                }
            }
        }
        return rowOrColMap;
    }

    /**
     * 设置行分组样式
     * @param stringChartStatisticsPojoEntry
     * @param keyList
     */
    private void setRowChild(ChartStatisticsPojo stringChartStatisticsPojoEntry, List<String> keyList,List<String> rowKeyValueList) {
        Map<String, ChartStatisticsPojo> childMap = stringChartStatisticsPojoEntry.getChildMap();
        if(childMap != null && !childMap.isEmpty()){
            //利用下一级的mapValues设置上级的childList
            Collection<ChartStatisticsPojo> values = childMap.values();
            List<ChartStatisticsPojo> child = (List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(values));
            stringChartStatisticsPojoEntry.setChild(child);
            for (ChartStatisticsPojo chartStatisticsPojo : stringChartStatisticsPojoEntry.getChild()) {
                StringBuffer innerParentKey = chartStatisticsPojo.getParentKey();
                if(innerParentKey == null){
                    innerParentKey = new StringBuffer();
                }
                innerParentKey.append(stringChartStatisticsPojoEntry.getParentKey()).append(chartStatisticsPojo.getOriginValue()).append("|");
                chartStatisticsPojo.setParentKey(innerParentKey);
                if(chartStatisticsPojo.getChildMap()!=null && !chartStatisticsPojo.getChildMap().isEmpty()){
                    chartStatisticsPojo.setChild((List<ChartStatisticsPojo>) CloneUtil.deepClone(new ArrayList<>(chartStatisticsPojo.getChildMap().values())));
                    setRowChild(chartStatisticsPojo,keyList,rowKeyValueList);
                }else {
                    keyList.add(chartStatisticsPojo.getParentKey().toString());
                    rowKeyValueList.add(chartStatisticsPojo.getParentKey().toString());
                }
            }
        }else {
            keyList.add(stringChartStatisticsPojoEntry.getParentKey().toString());
            rowKeyValueList.add(stringChartStatisticsPojoEntry.getParentKey().toString());
        }
    }

    private Map<String, String> valueListAnalysis(FieldAttrPojo field, List<String> values, ChartEntity chartEntity, BaseDTO baseDTO, Map<String, Map<String, String>> attrLinkMap) throws XbbException{
        return ckResultHelp.valueListAnalysis(field, baseDTO.getCorpid(), values, chartEntity, false, null, true, baseDTO,null,attrLinkMap);
    }
    /**
     * 根据不同的汇总方式 计算汇总值
     * @param values
     * @param aggType
     * @return java.lang.String
     */
    public String getSummaryTotal(List<String> values, String aggType) {
        String total = "0.0";
        values = values.stream().filter(StringUtil::isNotEmpty).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(values)) {
            return StringConstant.SHORT_BARS;
        }
        AggTypeEnum aggTypeEnum = AggTypeEnum.getByAlias(aggType);
        BigDecimal sumDecimal = new BigDecimal(total);
        switch (aggTypeEnum) {
            case MAX:
                total = Collections.max(values);
                break;
            case MIN:
                total = Collections.min(values);
                break;
            case AVG:
                BigDecimal countDecimal = new BigDecimal(values.size());
                for (String value : values) {
                    BigDecimal addDecimal = new BigDecimal(value);
                    sumDecimal = sumDecimal.add(addDecimal);
                }
                total = sumDecimal.divide(countDecimal, 6).toPlainString();
                break;
            case SUM:
            case COUNT:
            default:
                for (String value : values) {
                    //数据超出 1.7976931348623157E+103088 或者小于 -1.7976931348623157E+103088 的数值都展示成0.0
                    if (value.contains(PaasConstant.ES_INFINITY)) {
                        BigDecimal addDecimal = new BigDecimal("0.0");
                        sumDecimal = sumDecimal.add(addDecimal);
                    }else{
                        BigDecimal addDecimal = new BigDecimal(value);
                        sumDecimal = sumDecimal.add(addDecimal);
                    }
                }
                total = sumDecimal.toPlainString();
                break;
        }
        return total;
    }

    /**
     * 同环比旧值获取（统计表）
     * @param rowKey 行分组key
     * @param colKey 列分组key
     * @param yearChainOriginValMap 同环比原始值map，key:日期时间戳，val：原始统计值
     * @param key 拼接好的map内层key
     * @param summaryStatisticsPojo 统计值StatisticsPojo
     * @return java.lang.String 旧时间戳
     * @author xinpeng.jiang
     * @date 2021/12/16 21:24
     * @version 1.0
     */
    private String getOldVal4StatisticsTable(String rowKey, String colKey, Map<String, Map<String, ChartStatisticsPojo>> yearChainOriginValMap, String key, ChartStatisticsPojo summaryStatisticsPojo) {
        String oldVal = "0";
        FieldAttrPojo summaryFieldAttrPojo = summaryStatisticsPojo.getSummaryFieldAttrPojo();
        JSONArray advancedComputing = summaryFieldAttrPojo.getAdvancedComputing();
        FieldAttrPojo dateFieldAttrPojo = summaryStatisticsPojo.getDateFieldAttrPojo();
        Integer dateFieldIndex = summaryFieldAttrPojo.getDateFieldIndex();
        RowColIndexEnum rowColIndexEnum = RowColIndexEnum.getByCode(dateFieldIndex);
        List<String> splitValList;
        if (Objects.equals(rowColIndexEnum.getType(), RowColEnum.ROW.getValue())) {
            splitValList = Arrays.asList(rowKey.split("\\|"));
        } else {
            splitValList = Arrays.asList(colKey.split("\\|"));
        }
        Integer dateIndex = rowColIndexEnum.getIndex();
        if (CollectionsUtil.isNotEmpty(splitValList) && dateIndex <= splitValList.size()) {
            String nowTimestamp = splitValList.get(dateIndex);
            // 获取旧时间戳
            Long oldTimestamp = ckResultHelp.getYearChainDiff(dateFieldAttrPojo, advancedComputing, Long.valueOf(nowTimestamp));
            if (oldTimestamp == null) {
                return oldVal;
            }
            // 去map中拿旧值，拿不到就是0
            String rowColKey;
            if (Objects.equals(rowColIndexEnum.getType(), RowColEnum.ROW.getValue())) {
                rowColKey = oldTimestamp + "|" + colKey;
            } else {
                rowColKey = rowKey + oldTimestamp + "|";
            }
            Map<String, ChartStatisticsPojo> yearChainPojoMap = yearChainOriginValMap.get(rowColKey);
            if (yearChainPojoMap == null) {
                return oldVal;
            }
            ChartStatisticsPojo yearChainPojo = yearChainPojoMap.get(key);
            if (yearChainPojo == null) {
                return oldVal;
            }
            List<String> valueList = yearChainPojo.getOriginValues();
            if (CollectionUtils.isEmpty(valueList)) {
                return oldVal;
            }
            String val = valueList.get(0);
            if (StringUtil.isNotEmpty(val)) {
                return val;
            }
        }
        return oldVal;
    }

    private boolean setSummary(List<ChartStatisticsPojo> body, List<String> summaryList, Map<String, JSONObject> map, Map<String, AggFieldPojo> aggFieldMap, Map<String, FieldAttrPojo> summaryAttrMap) {
        if (CollectionsUtil.isEmpty(body)) {
            return false;
        }
        for (ChartStatisticsPojo chartStatisticsPojo : body) {
            List<ChartStatisticsPojo> child = chartStatisticsPojo.getChild();
            if (CollectionsUtil.isNotEmpty(child)) {
                boolean flag = setSummary(child,summaryList, map,aggFieldMap, summaryAttrMap);
                if(flag){
                    StringBuffer parentKey = chartStatisticsPojo.getParentKey();
                    if(parentKey != null && StringUtil.isNotEmpty(parentKey.toString())){
                        for (String s : aggFieldMap.keySet()) {
                            AggFieldPojo aggFieldPojo =  aggFieldMap.get(s);
                            String attr = aggFieldPojo.getAttr();
                            String aggName = attr + "&" + aggFieldPojo.getFieldType() + "&" + aggFieldPojo.getIndex();
                            FieldAttrPojo fieldAttrPojo = summaryAttrMap.get(aggName);
                            int accuracy = fieldAttrPojo.getAccuracy() == null ? 0 : fieldAttrPojo.getAccuracy();
                            Integer percentUsed = fieldAttrPojo.getPercentUsed();
                            Integer groupingUsed = fieldAttrPojo.getGroupingUsed() == null ? fieldAttrPojo.getAmountFlag() : fieldAttrPojo.getGroupingUsed();
                            Integer numFormat = fieldAttrPojo.getNumFormat();
                            NumFormatEnum numFormatEnum = NumFormatEnum.getByCode(numFormat);
                            String unit = numFormatEnum.getNoYuanUnit();
                            String formatVal = "";
                            if(map!=null && !map.isEmpty() && map.get(parentKey.toString()) !=null && StringUtils.isNotBlank(map.get(parentKey.toString()).getString(s))){
                                String newVal = String.valueOf(ChartResultUtil.formatVal4Num(new BigDecimal(map.get(parentKey.toString()).getString(s)), numFormatEnum,FieldAnalysisHelp.isPercentUsedOfAccuracy(percentUsed,accuracy)));
                                formatVal = attrDecimalPrecisionHelper.getNumberFormat(newVal, accuracy, groupingUsed, percentUsed);
                                if (StringUtil.isNotEmpty(unit)) {
                                    formatVal += unit;
                                }
                            }
                            summaryList.add(formatVal);
                        }
                    }
                }
            } else {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取统计表总计sql - 分组部分
     *
     * @param groupSqlVO  完整sql组成的部分
     * @param isUnder  是否下方总计   true-是   false-否 (右侧总计)
     * @return java.util.Map<java.lang.String,java.lang.String>
     * @author zyy
     * @date 2022/7/27
     * @version v1.0
     */
    public Map<String, String> getGroupSqlOfTotal(GroupSqlVO groupSqlVO, boolean isUnder) {
        Map<String,String> groupSqlMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        String groupColumn = "";
        String groupField = "";
        if(isUnder){
            //下方总计group
            if(CollectionUtils.isNotEmpty(groupSqlVO.getColGroupColumnsList())){
                groupColumn = String.join(XbbConstant.SPACE + XbbConstant.SQL_COMMA, groupSqlVO.getColGroupColumnsList());
                groupField = String.join(XbbConstant.SPACE + XbbConstant.SQL_COMMA, groupSqlVO.getColGroupFieldsList());
            }
        }else{
            //右侧总计group
            if(CollectionUtils.isNotEmpty(groupSqlVO.getRowGroupColumnsList())){
                groupColumn = String.join(XbbConstant.SPACE + XbbConstant.SQL_COMMA, groupSqlVO.getRowGroupColumnsList());
                groupField = String.join(XbbConstant.SPACE + XbbConstant.SQL_COMMA, groupSqlVO.getRowGroupFieldsList());
            }
        }
        groupSqlMap.put("groupColumn",groupColumn);
        groupSqlMap.put("groupField",groupField);
        return groupSqlMap;
    }

    /**
     * 判断是否存在计算字段类型并且汇总方式为非求和
     *
     * @param aggFieldMap 字段跟汇总方式的映射容器
     * @param colFiledList 列分组字段
     * @return boolean  true-存在计算字段类型，    false-不存在计算字段 或者 不存在列分组字段
     * @author zyy
     * @date 2022/8/26
     * @version v1.0
     */
    public boolean containsComputedField(Map<String, AggFieldPojo> aggFieldMap,List<String> colFiledList) {
        //默认不需要拼接sql
        boolean flag = false;

        if(CollectionsUtil.isEmpty(colFiledList)){
            //不存在列分组字段时，不重新拼接sql
            return flag;
        }

        for (Map.Entry<String, AggFieldPojo> fieldPojoEntry : aggFieldMap.entrySet()) {
            AggFieldPojo aggFieldPojo = fieldPojoEntry.getValue();
            if(Objects.equals(aggFieldPojo.getFieldType(),FieldTypeEnum.COMPUTED_FIELD.getType())){
                flag = true;
                //只要有一个字段需要重新发起查询请求，就结束循环
                break;
            }
        }
        return flag;
    }

    /**
     * 判断是否满足下拉类型字段的条件
     *
     * @param chartEntity 图表实体
     * @param fieldType 字段类型
     * @param sortMap 手动排序字段容器
     * @return boolean
     * @author zyy
     * @date 2022/10/20
     * @version v1.0
     */
    public boolean isComboFieldSort(ChartEntity chartEntity,Integer fieldType,Map<String, String> sortMap){
        //手动排序的优先级最高，如果存在手动排序就忽略下拉类型字段
        if(sortMap != null && sortMap.size() > 0){
            return false;
        }
        return ChartTypeEnum.comboChartCodeList().contains(chartEntity.getChartType()) && FieldTypeEnum.isReOrder4Combo(fieldType);
    }

    /**
     * 字段的默认排序sql拼接
     *
     * @param stringBuffer  总sql
     * @param groupFieldsList 分组字段数组
     * @author zyy
     * @date 2022/8/15
     * @version v1.0
     */
    public void defaultFieldSort(StringBuffer stringBuffer, List<String> groupFieldsList) {
        if(CollectionsUtil.isNotEmpty(groupFieldsList)){
            stringBuffer.append(XbbConstant.ORDER_BY);
            stringBuffer.append(String.join(String.format("%s%s%s", XbbConstant.SPACE, XbbConstant.ORDER_DESC, XbbConstant.SQL_COMMA), groupFieldsList));
            stringBuffer.append(XbbConstant.SPACE).append(XbbConstant.ORDER_DESC);
        }
    }

    /**
     * 处理钻取完之后结果集的渲染，以及钻取符号（“-”），以下参数有不懂的地方可以去ChartResultPojo对象中查看注释
     *
     * @param drillField            钻取的操作是针对行还是列
     * @param rowOrColGroupAttr     当前钻取图表的行或者列属性
     * @param chartAnalysisDTO      图表分析参数
     * @param chartEntity           当前图表信息
     * @return 钻取处理之后返回的临时行列分组信息
     */
    private List<FieldAttrPojo> dealTableRowOrColAttrDrillSign(String drillField, JSONArray rowOrColGroupAttr, ChartAnalysisDTO chartAnalysisDTO, ChartEntity chartEntity) {
        List<FieldAttrPojo> rowOrColGroupAttrList = JSONArray.parseArray(rowOrColGroupAttr.toJSONString(), FieldAttrPojo.class);

        ChartResultPojo chartResultPojo = chartAnalysisDTO.getChartResultPojo();
        if (Objects.isNull(chartResultPojo)) {
            return rowOrColGroupAttrList;
        }
        DrillResultPojo drillResultPojo = chartResultPojo.getDrillResultPojo();
        if (Objects.isNull(drillResultPojo)) {
            return rowOrColGroupAttrList;
        }
        Map<Long, DrillResultChartInfoPojo> resultChartInfoMap = drillResultPojo.getResultChartInfoMap();
        if (!drillResultPojo.getDrillFlag() || Objects.isNull(resultChartInfoMap) || resultChartInfoMap.isEmpty()) {
            return rowOrColGroupAttrList;
        }
        DrillResultChartInfoPojo drillResultChartInfoPojo = resultChartInfoMap.get(chartEntity.getId());
        if (Objects.isNull(drillResultChartInfoPojo)) {
            return rowOrColGroupAttrList;
        }
        Map<String, DrillResultChartFieldInfoPojo> chartFieldInfoMap = drillResultChartInfoPojo.getChartFieldInfoMap();
        if (Objects.isNull(chartFieldInfoMap) || chartFieldInfoMap.isEmpty()) {
            return rowOrColGroupAttrList;
        }
        DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo = chartFieldInfoMap.get(drillField);
        if (Objects.isNull(drillResultChartFieldInfoPojo)) {
            return rowOrColGroupAttrList;
        }

        // 需要拼接减号的集合字段，以及需要拼接表格返回结果的集合字段(也可以去对象中查看注释)
        List<FieldAttrPojo> conditionToTableList = drillResultChartFieldInfoPojo.getConditionToTableList();
        if (CollectionsUtil.isEmpty(conditionToTableList)) {
            return rowOrColGroupAttrList;
        }

        // 钻取操作之后的表头或者表体的数据
        List<FieldAttrPojo> newRowOrColGroupAttrList = new ArrayList<>();

        // 钻取后的指向字段，比如钻取层级为A -> B -> C，点击下钻B，goalDrillField为C；点击上卷B，则为A（也可以去对象中查看注释）
        FieldAttrPojo goalDrillField = drillResultChartFieldInfoPojo.getGoalDrillField();
        if (Objects.isNull(goalDrillField)) {
            return rowOrColGroupAttrList;
        }

        for (FieldAttrPojo fieldAttrPojo : rowOrColGroupAttrList) {
            String attr = fieldAttrPojo.getAttr();
            if (Objects.equals(attr, goalDrillField.getAttr())) {
                newRowOrColGroupAttrList.addAll(conditionToTableList);
            }
            newRowOrColGroupAttrList.add(fieldAttrPojo);
        }

        ReflectHelper.valueSet(chartEntity, drillField, JSON.parseArray(JSON.toJSONString(newRowOrColGroupAttrList)));
        return newRowOrColGroupAttrList;
    }

    /**
     * 获取某一张图的总钻取信息pojo，包含总筛选条件、钻取层级信息、以及钻取信息map
     *
     * @param chartAnalysisDTO 图表分析参数，就是传过来的
     * @param chartEntity      图表实体属性
     * @return 某一张图的总钻取信息pojo，包含总筛选条件、钻取层级信息和钻取信息map
     */
    private DrillResultChartInfoPojo getDrillResultChartInfoPojo(ChartAnalysisDTO chartAnalysisDTO, ChartEntity chartEntity) {
        ChartResultPojo chartResultPojo = chartAnalysisDTO.getChartResultPojo();
        DrillResultPojo drillResultPojo = chartResultPojo.getDrillResultPojo();
        if (Objects.isNull(drillResultPojo)) {
            return null;
        }
        Map<Long, DrillResultChartInfoPojo> resultChartInfoMap = drillResultPojo.getResultChartInfoMap();
        if (Objects.isNull(resultChartInfoMap) || resultChartInfoMap.isEmpty()) {
            return null;
        }
        return resultChartInfoMap.get(chartEntity.getId());
    }

    /**
     * 获取处理过的属性条件集合，具体详细注释可以去实体类中查看
     *
     * @param drillField               钻取的属性，对应DrillFieldEnum
     * @param drillResultChartInfoPojo 某一张图的总钻取信息pojo，包含总筛选条件、钻取层级信息和钻取信息map
     * @return 属性条件集合
     */
    private List<FieldAttrPojo> getConditionToTableList(String drillField, DrillResultChartInfoPojo drillResultChartInfoPojo) {
        if (Objects.isNull(drillResultChartInfoPojo)) {
            return null;
        }
        // 钻取图表的条件信息 （处理 “-” 号）
        Map<String, DrillResultChartFieldInfoPojo> chartFieldInfoMap = drillResultChartInfoPojo.getChartFieldInfoMap();
        if (Objects.isNull(chartFieldInfoMap) || chartFieldInfoMap.isEmpty()) {
            return null;
        }
        // 钻取方向（上卷、下钻）、钻取图表字段（分类、系列、行列）、当前钻取字段及其所属层级attrList等信息pojo
        DrillResultChartFieldInfoPojo drillResultChartFieldInfoPojo = chartFieldInfoMap.get(drillField);
        if (Objects.isNull(drillResultChartFieldInfoPojo)) {
            return null;
        }
        return drillResultChartFieldInfoPojo.getConditionToTableList();
    }

    /**
     * 处理钻取之后的上卷符号（“-”），以及特殊字段的下钻符号（“+”）
     *
     * @param pojo                 表的返回数据对象
     * @param fieldAttrPojo        当前表的行列属性
     * @param conditionToTableList 经过处理的条件属性集合，直接拼上钻取符号即可
     */
    private void dealDrillTableValueInfo(ChartStatisticsPojo pojo, FieldAttrPojo fieldAttrPojo, List<FieldAttrPojo> conditionToTableList) {
        if (CollectionsUtil.isEmpty(conditionToTableList) || StringUtil.isEmpty(pojo.getValue())) {
            return;
        }
        boolean flag = Objects.nonNull(fieldAttrPojo.getValueText());
        // 处理上卷符号（“-”）
        for (FieldAttrPojo attrPojo : conditionToTableList) {
            if (drillHelp.drillMatchRule(attrPojo, fieldAttrPojo)) {
                // 特殊字段（部门、产品分类等）这个地方特许处理成“+”,比如一级分类钻取成二级分类应该为“+”
                if (flag) {
                    pojo.setDrillDir(DrillDirEnum.UP.getAlias());
                } else {
                    pojo.setDrillDir(DrillDirEnum.DOWN.getAlias());
                }
                return;
            }
        }
    }
    /**
     * 处理钻取匹配规则（返回字段下钻，只处理下钻符号（“+”））
     *
     * @param pojo                     返回统计表信息pojo
     * @param fieldAttrPojo            当前统计表字段熟悉
     * @param drillResultChartInfoPojo 某一张图的总钻取信息pojo，包含总筛选条件、钻取层级信息和钻取信息map
     */
    private void dealDrillTableMatchInfo(ChartStatisticsPojo pojo, FieldAttrPojo fieldAttrPojo, DrillResultChartInfoPojo drillResultChartInfoPojo) {
        // 特殊处理部门和分类的value值为“0”时候的操作, 修改为可穿透不可钻取
        if ((FieldTypeEnum.getDeptList().contains(fieldAttrPojo.getFieldType()) && Objects.equals(StringConstant.ZERO, pojo.getValue()))
                || (FieldTypeEnum.categoryList().contains(fieldAttrPojo.getFieldType()) && Objects.equals(StringConstant.ZERO, pojo.getValue()))) {
            pojo.setValue("--");
            return;
        }
        if (Objects.isNull(drillResultChartInfoPojo) || StringUtil.isEmpty(pojo.getValue())) {
            return;
        }
        // 钻取层级字段
        List<ChartDrillItemPojo> drillList = drillResultChartInfoPojo.getDrillList();
        if (CollectionsUtil.isEmpty(drillList)) {
            return;
        }
        boolean empty = StringUtil.isEmpty(pojo.getDrillDir());
        // 统计表 (处理 “+” 号)
        for (ChartDrillItemPojo drillItemPojo : drillList) {
            List<FieldAttrPojo> field = drillItemPojo.getField();
            if (CollectionsUtil.isEmpty(field)) {
                continue;
            }
            int fieldSize = field.size();
            for (int i = 0; i < fieldSize; i++) {
                FieldAttrPojo drillFieldAttrPojo = field.get(i);
                if (drillHelp.drillMatchRule(drillFieldAttrPojo, fieldAttrPojo)) {
                    if (i < (fieldSize - 1)) {
                        if (empty) {
                            pojo.setDrillDir(DrillDirEnum.DOWN.getAlias());
                        }
                    }
                    if (i == (fieldSize - 1)) {
                        boolean downSameField = Objects.equals(ChartDrillWayEnum.DOWN_SAME_FIELD.getCode(), fieldAttrPojo.getDrillWay());
                        if (empty && downSameField) {
                            pojo.setDrillDir(DrillDirEnum.DOWN.getAlias());
                        }
                    }
                    return;
                }
            }
        }
    }

    /**
     * 统计表总计、小计 子查询外层SQL嵌套
     *
     * @param fromSql
     * @param groupSqlVO
     * @param groupColumn
     * @param split
     * @return java.lang.String
     * @author zyy
     * @date 2023/2/15
     * @version v1.0
     */
    public String dealSubQuerySqlByCount(String fromSql, GroupSqlVO groupSqlVO, String groupColumn,boolean split) {
        List<String> subQuerySqlOfCountList = groupSqlVO.getSubQuerySqlOfCountList();
        if(CollectionsUtil.isEmpty(subQuerySqlOfCountList)){
            //非子查询SQL写法则返回
            return fromSql;
        }
        StringBuilder sqlBuilder = new StringBuilder();
        //外层select部分
        List<String> summaryColumnAlisaList = new ArrayList<>(groupSqlVO.getSummaryColumnAlisa());
        summaryColumnAlisaList.addAll(subQuerySqlOfCountList);
        if(StringUtils.isNotBlank(groupColumn)){
            String[] groupColumnArray = groupColumn.split(XbbConstant.SPACE + XbbConstant.SQL_COMMA);
            for (String column : groupColumnArray) {
                String columnStr = column;
                if(split){
                    columnStr = column.split(XbbConstant.AS).length == BasicConstant.TWO ? column.split(XbbConstant.AS)[BasicConstant.ONE].trim() : column;
                }
                summaryColumnAlisaList.add(columnStr);
            }
        }
        String items = String.join(XbbConstant.SQL_COMMA, summaryColumnAlisaList);
        //组装外层SQL
        sqlBuilder.append(XbbConstant.SELECT).append(items).append(XbbConstant.SPACE)
                .append(XbbConstant.FROM).append(XbbConstant.L_P).append(fromSql).append(XbbConstant.R_P).append(XbbConstant.AS).append("T");
        return sqlBuilder.toString();
    }
}
